mirror of
https://gitee.com/BDWare/router-backend
synced 2025-01-09 17:34:05 +00:00
initial commit
This commit is contained in:
parent
ec08043ed3
commit
eebbe9d791
30
.gitignore
vendored
30
.gitignore
vendored
@ -1,18 +1,12 @@
|
||||
# Build and Release Folders
|
||||
bin-debug/
|
||||
bin-release/
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
|
||||
# Other files and folders
|
||||
.settings/
|
||||
|
||||
# Executables
|
||||
*.swf
|
||||
*.air
|
||||
*.ipa
|
||||
*.apk
|
||||
|
||||
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
|
||||
# should NOT be excluded as they contain compiler settings and other important
|
||||
# information for Eclipse / Flash Builder.
|
||||
/NodeCenterDB/
|
||||
/ssl
|
||||
/rocksdb
|
||||
/repoConf.json
|
||||
/ncFile.txt
|
||||
/handleRecords/*
|
||||
/handleRecords
|
||||
/router-frontend/WebContent/client
|
||||
/router-frontend/WebContent/client/
|
||||
/log
|
||||
/ncconfig.json*
|
||||
/WebContent
|
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM openjdk:8
|
||||
|
||||
ARG GOPRIVATE=bdware.org/*
|
||||
ARG GOPROXY=https://goproxy.cn
|
||||
|
||||
LABEL maintainer="caihuaqian@internetapi.cn"
|
||||
LABEL org.bdware.version="1.5.0"
|
||||
LABEL org.bdware.version.isproduction="false"
|
||||
LABEL org.bdware.release-date="2021-08-09"
|
||||
|
||||
COPY ./output /bdcluster
|
||||
WORKDIR /bdcluster
|
||||
VOLUME /bdcluster/NodeCenterDB /bdcluster/rocksdb
|
||||
ENTRYPOINT ["java"]
|
||||
CMD ["-Dfile.encoding=UTF-8", "-cp", "./libs/*:bdcluster.jar", "org.bdware.server.NodeCenterServer", "-service-port=21040", "-do-repo-ip=localhost","-do-repo-port=21042", "-enable-ssl=./ssl/chained.pem:./ssl/domain.pem"]
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
## Docker镜像制作
|
||||
把`Dockerfile`放到一个目录,同时把编译好的`bdcluster.zip`放到同一目录,并解压、制作镜像:
|
||||
```
|
||||
unzip -d ./bdserver/ bdcluster.zip
|
||||
docker build -t bdware/bdcluster .
|
||||
```
|
121
build.gradle
Normal file
121
build.gradle
Normal file
@ -0,0 +1,121 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'application'
|
||||
}
|
||||
|
||||
mainClassName = 'org.bdware.server.NodeCenterServer'
|
||||
|
||||
application {
|
||||
mainClass = mainClassName
|
||||
applicationDefaultJvmArgs = ['-Dfile.encoding=UTF-8']
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(":front-base")
|
||||
// https://mvnrepository.com/artifact/com.jianggujin/IKAnalyzer-lucene
|
||||
implementation 'com.jianggujin:IKAnalyzer-lucene:8.0.0'
|
||||
// https://mvnrepository.com/artifact/org.apache.lucene/lucene-core
|
||||
implementation 'org.apache.lucene:lucene-core:8.9.0'
|
||||
// https://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser
|
||||
implementation 'org.apache.lucene:lucene-queryparser:8.9.0'
|
||||
// https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common
|
||||
implementation 'org.apache.lucene:lucene-analyzers-common:8.9.0'
|
||||
// https://mvnrepository.com/artifact/org.apache.lucene/lucene-backward-codecs
|
||||
implementation 'org.apache.lucene:lucene-backward-codecs:8.9.0'
|
||||
implementation 'org.apache.lucene:lucene-analyzers-smartcn:8.9.0'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
}
|
||||
|
||||
jar {
|
||||
String libs = ''
|
||||
configurations.runtimeClasspath.each {
|
||||
libs = libs + " libs/" + it.name
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes 'Manifest-Version': project.version
|
||||
attributes 'Main-Class': mainClassName
|
||||
attributes 'Class-Path': libs
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources.dependsOn(":web-client:copyToCluster")
|
||||
tasks.processResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE)
|
||||
|
||||
task copyScript(type: Copy) {
|
||||
from("../script/") {
|
||||
include 'ncstart.sh'
|
||||
include 'ncstop.sh'
|
||||
include 'ncconfig.json.template'
|
||||
include 'updateCluster.sh'
|
||||
}
|
||||
into "./build/output"
|
||||
println("copyScript done !")
|
||||
}
|
||||
|
||||
task copySsl(type: Copy) {
|
||||
from './ssl'
|
||||
into './build/output/ssl'
|
||||
}
|
||||
|
||||
task copyLibs(type: Copy, dependsOn: ["copyScript", 'copySsl']) {
|
||||
from configurations.runtimeClasspath
|
||||
into "./build/output/libs/"
|
||||
}
|
||||
|
||||
//task copyJar(type: Exec, dependsOn: [":front-cluster:jar", ":front-cluster:copyLibs"]) {
|
||||
// println("copyJar start")
|
||||
// commandLine "cp", "./build/libs/$project.name-$version" + ".jar", "./build/output/bdcluster.jar"
|
||||
//}
|
||||
|
||||
task copyJar(type: Copy, dependsOn: [":front-cluster:jar", ":front-cluster:copyLibs"]) {
|
||||
from "./build/libs/$project.name-${project.version}.jar"
|
||||
into "./build/output"
|
||||
rename { String fileName -> "bdcluster.jar" }
|
||||
doFirst {
|
||||
println "copyJar start"
|
||||
}
|
||||
}
|
||||
|
||||
task copyWebContent(type: Copy) {
|
||||
from("./WebContent") {
|
||||
exclude 'client/BaaSClient.html'
|
||||
exclude 'client/README.md'
|
||||
exclude 'client/.idea/'
|
||||
exclude 'client/.gitignore'
|
||||
exclude '.idea/'
|
||||
}
|
||||
into "./build/output/WebContent"
|
||||
}
|
||||
|
||||
task buildBDServerClusterZip(type: Zip, dependsOn: [":front-cluster:copyWebContent", ":front-cluster:copyScript",
|
||||
":front-cluster:copyJar"]) {
|
||||
from './build/output/'
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
archiveFileName = 'bdserver-cluster.zip'
|
||||
destinationDirectory = file('build/')
|
||||
}
|
||||
|
||||
task buildBDClusterZip(type: Zip, dependsOn: [":front-cluster:buildBDServerClusterZip"]) {
|
||||
from('./build/output/') {
|
||||
include("libs/*")
|
||||
include("bdcluster.jar")
|
||||
}
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
archiveFileName = 'bdcluster.zip'
|
||||
destinationDirectory = file('build/')
|
||||
}
|
||||
|
||||
task buildWebContentZip(type: Zip, dependsOn: [":front-cluster:copyWebContent"]) {
|
||||
from "./build/output/WebContent"
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
archiveFileName = 'ClusterWebContent.zip'
|
||||
destinationDirectory = file('build/')
|
||||
}
|
||||
|
||||
task buildBundle(dependsOn: [":front-cluster:buildBDClusterZip", ":front-cluster:buildWebContentZip"]) {
|
||||
doLast {
|
||||
println "buildBundle in ./build/output/ successfully"
|
||||
}
|
||||
}
|
86
src/main/java/org/bdware/sc/udp/UDPMessage.java
Normal file
86
src/main/java/org/bdware/sc/udp/UDPMessage.java
Normal file
@ -0,0 +1,86 @@
|
||||
package org.bdware.sc.udp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class UDPMessage implements Serializable {
|
||||
private static final long serialVersionUID = -8103830946473687985L;
|
||||
int isPart = 0;
|
||||
public UDPMessageType type;
|
||||
public int id; // 要标记sender
|
||||
int order;
|
||||
int requestID;
|
||||
byte[] content;
|
||||
|
||||
public UDPMessage() {
|
||||
}
|
||||
|
||||
public void setIsPart(boolean isPart) {
|
||||
this.isPart = isPart ? 1 : 0;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
static int Len = 6000;// 1000
|
||||
|
||||
public List<UDPMessage> split() {
|
||||
List<UDPMessage> splited = new ArrayList<>();
|
||||
// System.out.println("[UDPMessage split] content.length" + content.length);
|
||||
if (content.length < Len) {
|
||||
splited.add(this);
|
||||
return splited;
|
||||
}
|
||||
for (int i = 0; i < content.length; i += Len) {
|
||||
UDPMessage msg = new UDPMessage();
|
||||
msg.isPart = 1;
|
||||
msg.id = this.id;
|
||||
msg.order = i / Len;
|
||||
if (i + Len > content.length) {
|
||||
msg.content = new byte[content.length - i];
|
||||
System.arraycopy(content, i, msg.content, 0, content.length - i);
|
||||
} else {
|
||||
msg.content = new byte[Len];
|
||||
System.arraycopy(content, i, msg.content, 0, Len);
|
||||
}
|
||||
splited.add(msg);
|
||||
}
|
||||
return splited;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
try {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
ObjectOutputStream output;
|
||||
output = new ObjectOutputStream(bo);
|
||||
output.writeObject(this);
|
||||
return bo.toByteArray();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static UDPMessage parse(byte[] data, int len) {
|
||||
try {
|
||||
ByteArrayInputStream bi = new ByteArrayInputStream(data);
|
||||
ObjectInputStream input = new ObjectInputStream(bi);
|
||||
return (UDPMessage) input.readObject();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
7
src/main/java/org/bdware/sc/udp/UDPMessageType.java
Normal file
7
src/main/java/org/bdware/sc/udp/UDPMessageType.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.bdware.sc.udp;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public enum UDPMessageType implements Serializable {
|
||||
shakeHand, request, reply
|
||||
}
|
20
src/main/java/org/bdware/sc/udp/UDPNode.java
Normal file
20
src/main/java/org/bdware/sc/udp/UDPNode.java
Normal file
@ -0,0 +1,20 @@
|
||||
package org.bdware.sc.udp;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import org.bdware.sc.conn.Node;
|
||||
|
||||
public class UDPNode extends Node {
|
||||
public UDPNode(SocketAddress addr) {
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
public int id;
|
||||
public long lastUpdatedTime;
|
||||
public SocketAddress addr;
|
||||
|
||||
public String getAddr() {
|
||||
InetSocketAddress inet4 = (InetSocketAddress) addr;
|
||||
return inet4.getHostString() + ":" + inet4.getPort();
|
||||
}
|
||||
}
|
207
src/main/java/org/bdware/server/NodeCenterServer.java
Normal file
207
src/main/java/org/bdware/server/NodeCenterServer.java
Normal file
@ -0,0 +1,207 @@
|
||||
package org.bdware.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.HttpServerCodec;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||
import io.netty.handler.ssl.OptionalSslHandler;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.bdware.sc.DoConfig;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.db.MultiIndexTimeRocksDBUtil;
|
||||
import org.bdware.server.irp.LocalLHSProxy;
|
||||
import org.bdware.server.nodecenter.*;
|
||||
import org.bdware.server.ws.DelimiterCodec;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class NodeCenterServer {
|
||||
public static final String PATH = "/NodeCenterWS";
|
||||
private static final String CONFIG_PATH = "ncconfig.json";
|
||||
private static final Logger LOGGER = LogManager.getLogger(NodeCenterServer.class);
|
||||
public static MultiIndexTimeRocksDBUtil nodeHttpLogDB =
|
||||
new MultiIndexTimeRocksDBUtil("./NodeCenterDB", NCTables.NodeHttpLog.toString());
|
||||
public static MultiIndexTimeRocksDBUtil nodeTcpLogDB =
|
||||
new MultiIndexTimeRocksDBUtil("./NodeCenterDB", NCTables.NodeTcpLog.toString());
|
||||
public static ExecutorService threadPool;
|
||||
public static ScheduledExecutorService scheduledThreadPool =
|
||||
Executors.newScheduledThreadPool(8);
|
||||
static SslContext sslContext = null;
|
||||
// static byte[] delimiter = "wonbifoodie".getBytes();
|
||||
|
||||
static {
|
||||
KeyValueDBUtil.setupNC();
|
||||
//TimeDBUtil.setupNC();
|
||||
Configurator.setLevel(
|
||||
"io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder",
|
||||
Level.OFF);
|
||||
Configurator.setLevel(
|
||||
"io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder",
|
||||
Level.OFF);
|
||||
}
|
||||
|
||||
public static void parseConf(CMDConf cmdConf) {
|
||||
LocalLHSProxy.port = cmdConf.doipPort;
|
||||
LocalLHSProxy.enabled = true;
|
||||
if (cmdConf.disableDoRepo) {
|
||||
DoConfig.callContractUsingDOI = false;
|
||||
}
|
||||
if (cmdConf.disableLocalLhs) {
|
||||
LocalLHSProxy.enabled = false;
|
||||
}
|
||||
if (!cmdConf.enableSsl.isEmpty()) {
|
||||
try {
|
||||
String[] filePaths = cmdConf.enableSsl.split(":");
|
||||
File chainedFile = new File(filePaths[0]), keyFile = new File(filePaths[1]);
|
||||
if (chainedFile.exists() && keyFile.exists()) {
|
||||
sslContext = SslContextBuilder.forServer(chainedFile, keyFile).build();
|
||||
}
|
||||
LOGGER.debug("Enable ssl, path: " + chainedFile.getPath());
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Enabling SSL failed.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (cmdConf.debug != null) {
|
||||
if (!cmdConf.debug.isEmpty()) {
|
||||
|
||||
try {
|
||||
String[] classes = cmdConf.debug.split(",");
|
||||
for (String clz : classes) {
|
||||
Configurator.setLevel(clz, Level.DEBUG);
|
||||
LOGGER.warn("set debug: " + clz);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cmdConf.overwrite) {
|
||||
cmdConf.write(CONFIG_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
File confFile = new File(CONFIG_PATH);
|
||||
File confTemplate = new File(CONFIG_PATH + ".template");
|
||||
if (!confTemplate.exists()) {
|
||||
CMDConf conf = new CMDConf();
|
||||
conf.write(confTemplate.getAbsolutePath());
|
||||
}
|
||||
if (!confFile.exists() && confTemplate.exists()) {
|
||||
FileUtils.copyFile(confTemplate, confFile);
|
||||
}
|
||||
CMDConf cmf = CMDConf.parseConf(CONFIG_PATH).parseArgs(args);
|
||||
|
||||
parseConf(cmf);
|
||||
|
||||
if (LocalLHSProxy.enabled) {
|
||||
threadPool = Executors.newSingleThreadExecutor();
|
||||
threadPool.execute(() -> {
|
||||
try {
|
||||
LocalLHSProxy.start();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("local LHS proxy failed: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listenSocket(cmf.servicePort + 1);
|
||||
OtherNCProxy.instance.init();
|
||||
|
||||
startHttp(cmf.servicePort);
|
||||
//System.out.println("PORT"+cmf.servicePort);
|
||||
}
|
||||
|
||||
public static void listenSocket(int port) throws Exception {
|
||||
LOGGER.info("listen socket at " + port);
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.option(ChannelOption.SO_BACKLOG, 100)
|
||||
.localAddress(port)
|
||||
.childHandler(
|
||||
new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel arg0) {
|
||||
arg0.pipeline()
|
||||
.addLast(new DelimiterCodec())
|
||||
.addLast(new NodeCenterFrameHandler());
|
||||
}
|
||||
});
|
||||
b.bind(port).sync().channel();
|
||||
}
|
||||
|
||||
public static void startHttp(int port) {
|
||||
LOGGER.info("start at: " + port);
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
ControlledChannelInitializer initializer = new ControlledChannelInitializer();
|
||||
b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.localAddress(port)
|
||||
.childHandler(initializer);
|
||||
final Channel ch = b.bind(port).sync().channel();
|
||||
ch.closeFuture().sync();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
bossGroup.shutdownGracefully();
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
public static void start(int port) {
|
||||
try {
|
||||
listenSocket(port + 1);
|
||||
NCUDPRunner.mainPort = port + 2;
|
||||
startHttp(port);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static class ControlledChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
NCHttpHandler handler = new NCHttpHandler();
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel arg0) {
|
||||
if (sslContext != null) {
|
||||
arg0.pipeline().addLast(new OptionalSslHandler(sslContext));
|
||||
} else {
|
||||
LOGGER.warn("disable ssl");
|
||||
}
|
||||
arg0.pipeline()
|
||||
.addLast(new HttpServerCodec())
|
||||
.addLast(new HttpObjectAggregator(65536))
|
||||
.addLast(new WebSocketServerProtocolHandler(PATH, null, true))
|
||||
.addLast(new ChunkedWriteHandler())
|
||||
.addLast(handler)
|
||||
.addLast(new NodeCenterWSFrameHandler());
|
||||
}
|
||||
}
|
||||
}
|
148
src/main/java/org/bdware/server/action/DistributeCallback.java
Normal file
148
src/main/java/org/bdware/server/action/DistributeCallback.java
Normal file
@ -0,0 +1,148 @@
|
||||
package org.bdware.server.action;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.nodecenter.CMNode;
|
||||
import org.bdware.server.nodecenter.NodeCenterActions;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DistributeCallback extends ResultCallback {
|
||||
private static final Logger LOGGER = LogManager.getLogger(DistributeCallback.class);
|
||||
String sponsorPubkey;// 发起节点的
|
||||
Map<String, String> nodes;
|
||||
String pubKey; //发起节点的用户公钥
|
||||
String signature; // 发起节点的
|
||||
int count; // 集群中几个节点已成功启动
|
||||
ResultCallback res; // 返回给Node
|
||||
String fileName; // ypk的文件名
|
||||
int index;
|
||||
String distributeID; //发起节点的分发id
|
||||
|
||||
public DistributeCallback(String ss, String sponID, Map<String, String> n, ResultCallback re, String p, String s) {
|
||||
distributeID = ss;
|
||||
count = 0;
|
||||
index = 1;
|
||||
this.res = re;
|
||||
this.pubKey = p;
|
||||
this.signature = p;
|
||||
this.sponsorPubkey = sponID;
|
||||
this.nodes = n;
|
||||
}
|
||||
|
||||
// 向集群中没有合约项目的节点发送合约
|
||||
public void distributeContractProject(String filePath, String isPrivate) {
|
||||
LOGGER.debug("[DistributeCallback] distributeContractProject : position----5" + filePath);
|
||||
|
||||
File f = new File(filePath);
|
||||
fileName = f.getName();
|
||||
LOGGER.debug("[DistributeCallback] distributeContractProject : fileName=" + fileName);
|
||||
LOGGER.debug("[DistributeCallback] nodeNames: " + JsonUtil.toJson(nodes));
|
||||
|
||||
for (String ID : nodes.keySet()) {
|
||||
if (ID.equals(sponsorPubkey))
|
||||
continue;
|
||||
CMNode node = NodeCenterActions.nodeInfos.get(ID);
|
||||
node.connection.sendProject(filePath, isPrivate, pubKey, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void NCreceive(String progress) {
|
||||
Map<String, String> ret2 = new HashMap<>();
|
||||
ret2.put("action", "onDistributeContract");
|
||||
ret2.put("progress", "NC is receiving ypk from sponsor,progress is " + progress + "%.");
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("action", "onDistribute");
|
||||
map.put("content", JsonUtil.toJson(ret2));
|
||||
map.put("distributeID", distributeID);
|
||||
res.onResult(JsonUtil.toJson(map));
|
||||
}
|
||||
|
||||
public void onDistribute(String progress) {
|
||||
Map<String, String> ret2 = new HashMap<>();
|
||||
ret2.put("action", "onDistributeContract");
|
||||
ret2.put(
|
||||
"progress",
|
||||
"NC is sending ypk to NO."
|
||||
+ index
|
||||
+ " node in the units,progress is "
|
||||
+ progress
|
||||
+ "%.");
|
||||
if (progress.equals("100.00")) index++;
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("action", "onDistribute");
|
||||
map.put("distributeID", distributeID);
|
||||
map.put("content", JsonUtil.toJson(ret2));
|
||||
res.onResult(JsonUtil.toJson(map));
|
||||
}
|
||||
|
||||
public void onReceive(Map<String, String> map) {
|
||||
LOGGER.debug("[DistributeCallback] onReceive : position----9");
|
||||
String progress = map.get("progress");
|
||||
|
||||
if (progress.equals("100")) {
|
||||
Map<String, String> args = new HashMap<>();
|
||||
|
||||
args.put("fileName", fileName);
|
||||
args.put("pubKey", pubKey);
|
||||
args.put("signature", signature);
|
||||
|
||||
count++;
|
||||
|
||||
LOGGER.debug(count + "个节点已收完成" + " 总共有" + nodes.size() + " 个节点");
|
||||
|
||||
if (count == nodes.size()) {
|
||||
// res返回给前端,合约分发完成
|
||||
Map<String, String> ret2 = new HashMap<>();
|
||||
ret2.put("action", "onDistributeFinish");
|
||||
ret2.put("progress", "100%");
|
||||
Map<String, String> map_send = new HashMap<>();
|
||||
map_send.put("action", "onDistribute");
|
||||
map_send.put("over", "true");
|
||||
map_send.put("distributeID", distributeID);
|
||||
map_send.put("content", JsonUtil.toJson(ret2));
|
||||
res.onResult(JsonUtil.toJson(map_send));
|
||||
//NC delete file
|
||||
File file = new File("./temp/stateFiles/" + fileName);
|
||||
if (file.exists() && file.isFile())
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(String str) {
|
||||
LOGGER.debug("[DistributeCallback] str=" + str);
|
||||
|
||||
Map<String, String> map = JsonUtil.fromJson(str, new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
|
||||
NodeCenterActions.sync.sleepWithTimeout(map.get("requestID"), this, 60);
|
||||
|
||||
String operation = map.get("operation");
|
||||
|
||||
switch (operation) {
|
||||
case "NCreceive":
|
||||
NCreceive(map.get("progress"));
|
||||
break;
|
||||
case "distribute":
|
||||
distributeContractProject(map.get("receiveFileName"), map.get("isPrivate"));
|
||||
break;
|
||||
case "onDistribute":
|
||||
onDistribute(map.get("progress"));
|
||||
break;
|
||||
case "onReceive":
|
||||
onReceive(map);
|
||||
break;
|
||||
default:
|
||||
LOGGER.debug("[DistributeCallback] undefined operation " + operation);
|
||||
}
|
||||
}
|
||||
}
|
172
src/main/java/org/bdware/server/action/RequestAllExecutor.java
Normal file
172
src/main/java/org/bdware/server/action/RequestAllExecutor.java
Normal file
@ -0,0 +1,172 @@
|
||||
package org.bdware.server.action;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.ContractResult;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.nodecenter.CMNode;
|
||||
import org.bdware.server.nodecenter.ContractExecutor;
|
||||
import org.bdware.server.nodecenter.MultiPointContractInfo;
|
||||
import org.bdware.server.nodecenter.NodeCenterActions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class RequestAllExecutor implements ContractExecutor {
|
||||
private static final Logger LOGGER = LogManager.getLogger(RequestAllExecutor.class);
|
||||
MultiPointContractInfo info;
|
||||
int resultCount;
|
||||
|
||||
public RequestAllExecutor(MultiPointContractInfo minfo, int count) {
|
||||
info = minfo;
|
||||
resultCount = count;
|
||||
}
|
||||
|
||||
public ResultCallback createResultCallback(
|
||||
final String requestID, final ResultCallback originalCb, int count, String contractID) {
|
||||
return new Collector(requestID, originalCb, count, contractID);
|
||||
}
|
||||
|
||||
//only for test ADSP
|
||||
// public ResultCallback createResultCallback(
|
||||
// final String requestID, final ResultCallback originalCb, int count,String contractID,String seq) {
|
||||
// ResultCallback collector = new Collector(requestID, originalCb, count,contractID,seq);
|
||||
// return collector;
|
||||
// }
|
||||
|
||||
public void sendRequest(String req, ResultCallback collector) {
|
||||
List<String> nodes = info.members;
|
||||
for (String node : nodes) {
|
||||
CMNode cmNode = NodeCenterActions.nodeInfos.get(node);
|
||||
if (cmNode == null) {
|
||||
collector.onResult(
|
||||
"{\"status\":\"Error\",\"result\":\"node "
|
||||
+ node
|
||||
+ " offline\",\"action\":\"onExecuteContractTrustfully\"}");
|
||||
} else {
|
||||
cmNode.connection.controller.sendMsg(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String requestID, ResultCallback rc, String req) {
|
||||
JsonObject jo2 = JsonParser.parseString(req).getAsJsonObject();
|
||||
String id = jo2.get("contractID").getAsString();
|
||||
|
||||
//only for test ADSP
|
||||
// ResultCallback collector = createResultCallback(requestID, rc, resultCount,id,jo2.get("seq").getAsString());
|
||||
|
||||
ResultCallback collector = createResultCallback(requestID, rc, resultCount, id);
|
||||
|
||||
//TODO NC.sync?有问题?
|
||||
NodeCenterActions.sync.sleep(requestID, collector);
|
||||
sendRequest(req, collector);
|
||||
}
|
||||
|
||||
static class Collector extends ResultCallback {
|
||||
String contractID;
|
||||
int total;
|
||||
String requestID;
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
|
||||
//only for testADSP
|
||||
// boolean flag = true; //true表示还没在文件中记录这次调用结果
|
||||
// String seq;
|
||||
// Map<String,Integer> res = new ConcurrentHashMap<String,Integer>();
|
||||
|
||||
|
||||
//only for test ADSP
|
||||
// public Collector(String reqID, ResultCallback callback, int c,String id,String seq2) {
|
||||
// total = c;
|
||||
// requestID = reqID;
|
||||
// commiter = callback;
|
||||
// contractID = id;
|
||||
// seq = seq2;
|
||||
// }
|
||||
ResultCallback committer;
|
||||
|
||||
public Collector(String reqID, ResultCallback callback, int c, String id) {
|
||||
total = c;
|
||||
requestID = reqID;
|
||||
committer = callback;
|
||||
contractID = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(String str) {
|
||||
JsonObject obj = JsonParser.parseString(str).getAsJsonObject();
|
||||
obj.remove("action");
|
||||
obj.addProperty("action", "onExecuteContractTrustfully");
|
||||
obj.addProperty("seqNum", count.getAndIncrement());
|
||||
obj.addProperty("total", total);
|
||||
|
||||
//NodeCenterActions.recoverMap.get(nodePubKey).get(contractID).lastExeSeq++;
|
||||
|
||||
if (committer != null)
|
||||
committer.onResult(obj.toString());
|
||||
if (count.get() < total) {
|
||||
NodeCenterActions.sync.sleepWithTimeout(requestID, this, 10);
|
||||
}
|
||||
|
||||
String name = "null";
|
||||
if (obj.has("nodeID")) {
|
||||
String nodePubKey = obj.get("nodeID").getAsString();
|
||||
CMNode node = NodeCenterActions.nodeInfos.get(nodePubKey);
|
||||
name = node.nodeName;
|
||||
}
|
||||
LOGGER.debug("收到第 " + count.get() + " 个节点 " + name + " 回复 : " + obj);
|
||||
|
||||
if (obj.has("data")) {
|
||||
String data = obj.get("data").getAsString();
|
||||
ContractResult cr = JsonUtil.fromJson(data, ContractResult.class);
|
||||
|
||||
//only for testADSP
|
||||
// if(TestADSP.getFlag()){
|
||||
// String r = cr.result;
|
||||
// if(!res.containsKey(r)){
|
||||
// res.put(r,0);
|
||||
// }
|
||||
// int former = res.get(r);
|
||||
// res.put(r,++former);
|
||||
// for(String s : res.keySet()){
|
||||
// if(res.get(s) > total / 2 && flag){
|
||||
// //写入文件
|
||||
// File file = new File(TestADSP.resultPath);
|
||||
// synchronized (file){
|
||||
// try {
|
||||
// FileWriter fw = new FileWriter(file, true);
|
||||
// PrintWriter pw = new PrintWriter(fw);
|
||||
// pw.println(seq + " " + r);
|
||||
// pw.flush();
|
||||
// fw.flush();
|
||||
// pw.close();
|
||||
// fw.close();
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// flag = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/* if (cr.status == ContractResult.Status.Error) { //TODO 规范Status的使用 改成 ==Statuc.Error才恢复
|
||||
String nodePubKey = obj.get("nodeID").getAsString();
|
||||
if(NodeCenterActions.recoverMap.containsKey(nodePubKey)){
|
||||
ContractRecord record = NodeCenterActions.recoverMap.get(nodePubKey).get(contractID);
|
||||
if(record.recoverFlag == RecoverFlag.Fine){
|
||||
record.recoverFlag = RecoverFlag.ToRecover;
|
||||
MasterActions.restartContracts(nodePubKey);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package org.bdware.server.action;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.server.nodecenter.CMNode;
|
||||
import org.bdware.server.nodecenter.ContractExecutor;
|
||||
import org.bdware.server.nodecenter.MultiPointContractInfo;
|
||||
import org.bdware.server.nodecenter.NodeCenterActions;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class RequestOnceExecutor implements ContractExecutor {
|
||||
private static final Logger LOGGER = LogManager.getLogger(RequestOnceExecutor.class);
|
||||
MultiPointContractInfo info;
|
||||
AtomicInteger order = new AtomicInteger(0);
|
||||
|
||||
public RequestOnceExecutor(MultiPointContractInfo minfo) {
|
||||
info = minfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String requestID, ResultCallback rc, String req) {
|
||||
JsonObject jo2 = (new JsonParser()).parse(req).getAsJsonObject();
|
||||
String contractID = jo2.get("contractID").getAsString();
|
||||
|
||||
ResultCallback cb =
|
||||
new ResultCallback() {
|
||||
@Override
|
||||
public void onResult(String str) {
|
||||
LOGGER.debug(str);
|
||||
JsonObject jo = (new JsonParser()).parse(str).getAsJsonObject();
|
||||
jo.remove("action");
|
||||
jo.addProperty("action", "onExecuteResult");
|
||||
LOGGER.debug(jo.toString());
|
||||
rc.onResult(jo.toString());
|
||||
}
|
||||
};
|
||||
NodeCenterActions.sync.sleep(requestID, cb);
|
||||
for (int i = 0; i < info.members.size(); i++) {
|
||||
int size = info.members.size();
|
||||
String nodeID = info.members.get(order.incrementAndGet() % size);
|
||||
CMNode cmNode = NodeCenterActions.nodeInfos.get(nodeID);
|
||||
|
||||
if (cmNode != null) {
|
||||
cmNode.connection.controller.sendMsg(req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rc.onResult(
|
||||
"{\"status\":\"Error\",\"result\":\"all nodes "
|
||||
+ " offline\",\"action\":\"onExecuteContract\"}");
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package org.bdware.server.action;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.ContractResult;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.nodecenter.CMNode;
|
||||
import org.bdware.server.nodecenter.ContractExecutor;
|
||||
import org.bdware.server.nodecenter.MultiPointContractInfo;
|
||||
import org.bdware.server.nodecenter.NodeCenterActions;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ResponseOnceExecutor implements ContractExecutor {
|
||||
private static final Logger LOGGER = LogManager.getLogger(ResponseOnceExecutor.class);
|
||||
MultiPointContractInfo info;
|
||||
AtomicInteger order = new AtomicInteger(0);
|
||||
|
||||
public ResponseOnceExecutor(MultiPointContractInfo minfo) {
|
||||
info = minfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String requestID, ResultCallback rc, String req) {
|
||||
executeInternal(requestID, rc, req, 2);
|
||||
}
|
||||
|
||||
private void executeInternal(String requestID, ResultCallback rc, String req, int count) {
|
||||
JsonObject jo2 = (new JsonParser()).parse(req).getAsJsonObject();
|
||||
String contractID = jo2.get("contractID").getAsString();
|
||||
// TODO 标注失效节点,是否选择重新迁移??
|
||||
ResultCallback cb =
|
||||
new ResultCallback() {
|
||||
@Override
|
||||
public void onResult(String str) {
|
||||
LOGGER.debug(str);
|
||||
JsonObject jo = (new JsonParser()).parse(str).getAsJsonObject();
|
||||
jo.remove("action");
|
||||
jo.addProperty("action", "onExecuteResult");
|
||||
LOGGER.debug(jo.toString());
|
||||
if (jo.has("data")) {
|
||||
String data = jo.get("data").getAsString();
|
||||
ContractResult cr = JsonUtil.fromJson(data, ContractResult.class);
|
||||
if (cr.status != ContractResult.Status.Success && count > 0) {
|
||||
executeInternal(requestID, rc, req, count - 1);
|
||||
} else
|
||||
rc.onResult(jo.toString());
|
||||
} else {
|
||||
JsonObject jo2 = new JsonObject();
|
||||
jo2.addProperty("action", "onExecuteResult");
|
||||
jo.remove("action");
|
||||
jo2.addProperty("data", jo.toString());
|
||||
rc.onResult(jo2.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
NodeCenterActions.sync.sleepWithTimeout(requestID, cb, 5);
|
||||
if (!sendOnce(req))
|
||||
rc.onResult(
|
||||
"{\"status\":\"Error\",\"data\":\"{\\\"status\\\":\\\"Error\\\",\\\"result\\\":\\\"all nodes offline\\\"}\",\"action\":\"onExecuteContract\"}");
|
||||
}
|
||||
|
||||
private boolean sendOnce(String req) {
|
||||
JsonObject jo2 = (new JsonParser()).parse(req).getAsJsonObject();
|
||||
String contractID = jo2.get("contractID").getAsString();
|
||||
|
||||
for (int i = 0; i < info.members.size(); i++) {
|
||||
int size = info.members.size();
|
||||
String nodeID = info.members.get(order.incrementAndGet() % size);
|
||||
CMNode cmNode = NodeCenterActions.nodeInfos.get(nodeID);
|
||||
|
||||
if (cmNode != null) {
|
||||
cmNode.connection.controller.sendMsg(req);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
123
src/main/java/org/bdware/server/irp/LocalLHSProxy.java
Normal file
123
src/main/java/org/bdware/server/irp/LocalLHSProxy.java
Normal file
@ -0,0 +1,123 @@
|
||||
package org.bdware.server.irp;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.rocksdb.Options;
|
||||
import org.rocksdb.RocksDB;
|
||||
import org.rocksdb.RocksDBException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LocalLHSProxy {
|
||||
private static final Logger LOGGER = LogManager.getLogger(LocalLHSProxy.class);
|
||||
public static String PREFIX = "86.5000.470/";
|
||||
public static int port = 18007;
|
||||
public static boolean enabled = false;
|
||||
public static RocksDB db;
|
||||
static RegisterHandler registerHandler;
|
||||
|
||||
static {
|
||||
RocksDB.loadLibrary();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
start();
|
||||
}
|
||||
|
||||
public static void start() throws IOException, RocksDBException {
|
||||
String dbPath = "./handleRecords/";
|
||||
Options rockopts = new Options().setCreateIfMissing(true);
|
||||
rockopts.useFixedLengthPrefixExtractor(15);
|
||||
LOGGER.info("actual rocksdb path: " + new File(dbPath).getAbsolutePath());
|
||||
File lock = new File(dbPath, "LOCK");
|
||||
if (lock.exists()) {
|
||||
LOGGER.trace("remove file " + lock.getAbsolutePath() + ": " + lock.delete());
|
||||
}
|
||||
db = RocksDB.open(rockopts, dbPath);
|
||||
|
||||
registerHandler = new RegisterHandler(db);
|
||||
|
||||
LOGGER.info("listen to " + port);
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
|
||||
server.createContext("/test", new TestHandler());
|
||||
server.createContext("/resolve", new ResolveHandler());
|
||||
server.createContext("/local/", registerHandler);
|
||||
server.createContext("/view", new ViewHandler(db));
|
||||
server.start();
|
||||
}
|
||||
|
||||
private static Map<String, String> formData2Dic(String formData) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
if (formData == null || formData.trim().length() == 0) {
|
||||
return result;
|
||||
}
|
||||
final String[] items = formData.split("&");
|
||||
Arrays.stream(items)
|
||||
.forEach(
|
||||
item -> {
|
||||
final String[] keyAndVal = item.split("=");
|
||||
if (keyAndVal.length == 2) {
|
||||
try {
|
||||
final String key = URLDecoder.decode(keyAndVal[0], "utf8");
|
||||
final String val = URLDecoder.decode(keyAndVal[1], "utf8");
|
||||
result.put(key, val);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static class TestHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) {
|
||||
String response = "hello world";
|
||||
try {
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStream os = exchange.getResponseBody();
|
||||
os.write(response.getBytes());
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ResolveHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) {
|
||||
try {
|
||||
// 获得查询字符串(get)
|
||||
String queryString = exchange.getRequestURI().getQuery();
|
||||
Map<String, String> queryStringInfo = formData2Dic(queryString);
|
||||
String id = queryStringInfo.get("identifier");
|
||||
Map<String, String> respMap;
|
||||
respMap = registerHandler.handleResolve(queryStringInfo);
|
||||
respMap.forEach((k, v) -> {
|
||||
LOGGER.debug(k + "->" + v);
|
||||
});
|
||||
exchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStream os = exchange.getResponseBody();
|
||||
os.write(JsonUtil.toJson(respMap).getBytes());
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
246
src/main/java/org/bdware/server/irp/RegisterHandler.java
Normal file
246
src/main/java/org/bdware/server/irp/RegisterHandler.java
Normal file
@ -0,0 +1,246 @@
|
||||
package org.bdware.server.irp;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.rocksdb.RocksDB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class RegisterHandler implements HttpHandler {
|
||||
RocksDB db;
|
||||
String dbPath = "./handleRecords/";
|
||||
|
||||
public RegisterHandler(RocksDB rocksDB) {
|
||||
db = rocksDB;
|
||||
}
|
||||
|
||||
public Map<String, String> HandleRequest(Map<String, String> postInfo) {
|
||||
Map<String, String> respMap = new HashMap<>();
|
||||
String action = postInfo.get("action");
|
||||
switch (action) {
|
||||
case "resolve":
|
||||
respMap = handleResolve(postInfo);
|
||||
break;
|
||||
case "register":
|
||||
case "forceRegister":
|
||||
respMap = handleRegister(postInfo);
|
||||
break;
|
||||
case "unregister":
|
||||
case "forceDelete":
|
||||
respMap = handleUnRegister(postInfo);
|
||||
break;
|
||||
case "reregister":
|
||||
respMap = handleReregister(postInfo);
|
||||
break;
|
||||
default:
|
||||
System.out.println("error response");
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, String> handleRegister(Map<String, String> reqMap) {
|
||||
Map<String, String> respMap = new HashMap<>();
|
||||
String type;
|
||||
switch (reqMap.get("hrType")) {
|
||||
case "do":
|
||||
type = "do.";
|
||||
ViewHandler.handleRecordCount.doCount++;
|
||||
break;
|
||||
case "dou":
|
||||
type = "dou.";
|
||||
ViewHandler.handleRecordCount.userCount++;
|
||||
break;
|
||||
case "doip":
|
||||
type = "doip.";
|
||||
ViewHandler.handleRecordCount.repoCount++;
|
||||
break;
|
||||
default:
|
||||
type = "ukw.";
|
||||
break;
|
||||
}
|
||||
String identifier = LocalLHSProxy.PREFIX + type + geneRandomID() + "_bdw";
|
||||
reqMap.remove("action");
|
||||
reqMap.remove("hrType");
|
||||
reqMap.put("identifier", identifier);
|
||||
String handleRecord = JsonUtil.toJson(reqMap);
|
||||
try {
|
||||
db.put(identifier.getBytes(), handleRecord.getBytes());
|
||||
System.out.println("successful update do, identifier: " + identifier);
|
||||
respMap.put("identifier", identifier);
|
||||
respMap.put("status", "1");
|
||||
respMap.put("response", "register DO success, identifier: " + identifier);
|
||||
ViewHandler.addRegister();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "respond failed from LHS");
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, String> handleReregister(Map<String, String> reqMap) {
|
||||
Map<String, String> respMap = new HashMap<>();
|
||||
String identifier;
|
||||
if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
|
||||
else {
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "identifier not found");
|
||||
return respMap;
|
||||
}
|
||||
try {
|
||||
reqMap.remove("action");
|
||||
reqMap.remove("hrType");
|
||||
String handleRecord = JsonUtil.toJson(reqMap);
|
||||
if (db.get(identifier.getBytes()) == null) {
|
||||
String idType;
|
||||
if ((identifier.split("/")).length > 2)
|
||||
idType = identifier.split("/")[1].split("\\.")[0];
|
||||
else
|
||||
idType = identifier.split("\\.")[0];
|
||||
switch (idType) {
|
||||
case "do":
|
||||
ViewHandler.handleRecordCount.doCount++;
|
||||
break;
|
||||
case "dou":
|
||||
ViewHandler.handleRecordCount.userCount++;
|
||||
break;
|
||||
case "doip":
|
||||
ViewHandler.handleRecordCount.repoCount++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
db.delete(identifier.getBytes());
|
||||
}
|
||||
|
||||
db.put(identifier.getBytes(), handleRecord.getBytes());
|
||||
System.out.println("successful update do, identifier: " + identifier);
|
||||
respMap.put("identifier", identifier);
|
||||
respMap.put("status", "1");
|
||||
respMap.put("response", "reRegister DO success, identifier: " + identifier);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "unregister failed: " + e.getMessage());
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, String> handleUnRegister(Map<String, String> reqMap) {
|
||||
Map<String, String> respMap = new HashMap<>();
|
||||
String identifier;
|
||||
if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
|
||||
else {
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "identifier not found");
|
||||
return respMap;
|
||||
}
|
||||
try {
|
||||
switch (identifier.split("\\.")[2]) {
|
||||
case "470/do":
|
||||
ViewHandler.handleRecordCount.doCount--;
|
||||
break;
|
||||
case "470/doip":
|
||||
ViewHandler.handleRecordCount.repoCount--;
|
||||
break;
|
||||
case "470/dou":
|
||||
ViewHandler.handleRecordCount.userCount--;
|
||||
break;
|
||||
}
|
||||
db.delete(identifier.getBytes());
|
||||
respMap.put("status", "1");
|
||||
respMap.put("response", "success delete: " + identifier);
|
||||
ViewHandler.addDelete();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "unregister failed: " + e.getMessage());
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, String> handleResolve(Map<String, String> reqMap) {
|
||||
Map<String, String> respMap = new HashMap<>();
|
||||
String identifier;
|
||||
if (reqMap.get("identifier") != null) identifier = reqMap.get("identifier");
|
||||
else {
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "identifier not found");
|
||||
return respMap;
|
||||
}
|
||||
try {
|
||||
if (db.get(identifier.getBytes()) == null) {
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "not exist");
|
||||
return respMap;
|
||||
}
|
||||
String result = new String(db.get(identifier.getBytes()));
|
||||
respMap = JsonUtil.fromJson(result, HashMap.class);
|
||||
ViewHandler.addResolve();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
respMap.put("status", "0");
|
||||
respMap.put("response", "resolve failed: " + e.getMessage());
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public String geneRandomID() {
|
||||
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
Random random = new Random();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int number = random.nextInt(62);
|
||||
sb.append(str.charAt(number));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
Map<String, String> respMap;
|
||||
try {
|
||||
//获得表单提交数据(post)
|
||||
String postString = IOUtils.toString(exchange.getRequestBody());
|
||||
Map<String, String> postInfo = formData2Dic(postString);
|
||||
respMap = HandleRequest(postInfo);
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
OutputStream os = exchange.getResponseBody();
|
||||
os.write(JsonUtil.toJson(respMap).getBytes());
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> formData2Dic(String formData) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
if (formData == null || formData.trim().length() == 0) {
|
||||
return result;
|
||||
}
|
||||
final String[] items = formData.split("&");
|
||||
Arrays.stream(items).forEach(item -> {
|
||||
final String[] keyAndVal = item.split("=");
|
||||
if (keyAndVal.length == 2) {
|
||||
try {
|
||||
final String key = URLDecoder.decode(keyAndVal[0], "utf8");
|
||||
final String val = URLDecoder.decode(keyAndVal[1], "utf8");
|
||||
result.put(key, val);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
11
src/main/java/org/bdware/server/irp/StatisticsByDay.java
Normal file
11
src/main/java/org/bdware/server/irp/StatisticsByDay.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.bdware.server.irp;
|
||||
|
||||
public class StatisticsByDay {
|
||||
int resolveStatics;
|
||||
int deleteStatics;
|
||||
int registerStatics;
|
||||
|
||||
public StatisticsByDay(){
|
||||
registerStatics = resolveStatics = deleteStatics = 0;
|
||||
}
|
||||
}
|
257
src/main/java/org/bdware/server/irp/ViewHandler.java
Normal file
257
src/main/java/org/bdware/server/irp/ViewHandler.java
Normal file
@ -0,0 +1,257 @@
|
||||
package org.bdware.server.irp;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.rocksdb.ReadOptions;
|
||||
import org.rocksdb.RocksDB;
|
||||
import org.rocksdb.RocksDBException;
|
||||
import org.rocksdb.RocksIterator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ViewHandler implements HttpHandler {
|
||||
public static final String STATISTICS_KEY = "STATISTICS";
|
||||
public static final String COUNT_KEY = "COUNT";
|
||||
private static final Logger LOGGER = LogManager.getLogger(ViewHandler.class);
|
||||
public static HashMap<String, StatisticsByDay> lhsStatics = new HashMap<>();
|
||||
public static HandleRecordCount handleRecordCount;
|
||||
RocksDB db;
|
||||
|
||||
public ViewHandler(RocksDB rocksDB) throws RocksDBException {
|
||||
db = rocksDB;
|
||||
loadFromDB();
|
||||
NodeCenterServer.scheduledThreadPool.scheduleWithFixedDelay(
|
||||
() -> {
|
||||
try {
|
||||
saveToDB();
|
||||
} catch (RocksDBException e) {
|
||||
LOGGER.error("saving to DB failed! " + e.getMessage());
|
||||
}
|
||||
},
|
||||
0,
|
||||
1,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static String getToday() {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
|
||||
Date date = new Date(System.currentTimeMillis());
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
public static void addResolve() {
|
||||
String todayDate = ViewHandler.getToday();
|
||||
if (lhsStatics.get(todayDate) == null) {
|
||||
StatisticsByDay statisticsByDay = new StatisticsByDay();
|
||||
statisticsByDay.resolveStatics++;
|
||||
lhsStatics.put(todayDate, statisticsByDay);
|
||||
} else {
|
||||
lhsStatics.get(todayDate).resolveStatics++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addRegister() {
|
||||
String todayDate = ViewHandler.getToday();
|
||||
if (lhsStatics.get(todayDate) == null) {
|
||||
StatisticsByDay statisticsByDay = new StatisticsByDay();
|
||||
statisticsByDay.registerStatics++;
|
||||
lhsStatics.put(todayDate, statisticsByDay);
|
||||
} else {
|
||||
lhsStatics.get(todayDate).registerStatics++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDelete() {
|
||||
String todayDate = ViewHandler.getToday();
|
||||
if (lhsStatics.get(todayDate) == null) {
|
||||
StatisticsByDay statisticsByDay = new StatisticsByDay();
|
||||
statisticsByDay.deleteStatics++;
|
||||
lhsStatics.put(todayDate, statisticsByDay);
|
||||
} else {
|
||||
lhsStatics.get(todayDate).deleteStatics++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange httpExchange) throws IOException {
|
||||
Map<String, Object> respMap;
|
||||
try {
|
||||
//获得表单提交数据(post)
|
||||
String postString = httpExchange.getRequestURI().getQuery();
|
||||
Map<String, String> params = formData2Dic(postString);
|
||||
respMap = HandleRequest(params);
|
||||
httpExchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
|
||||
httpExchange.sendResponseHeaders(200, 0);
|
||||
OutputStream os = httpExchange.getResponseBody();
|
||||
os.write(JsonUtil.toJson(respMap).getBytes());
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> HandleRequest(Map<String, String> postInfo) {
|
||||
Map<String, Object> respMap = new HashMap<>();
|
||||
String action = postInfo.get("action");
|
||||
switch (action) {
|
||||
case "count":
|
||||
respMap = getLHSCount();
|
||||
break;
|
||||
case "statistics":
|
||||
respMap = getLHSStatics(postInfo);
|
||||
break;
|
||||
default:
|
||||
System.out.println("error response");
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
private void loadFromDB() throws RocksDBException {
|
||||
byte[] statisticBytes = db.get(STATISTICS_KEY.getBytes());
|
||||
if (statisticBytes == null) {
|
||||
lhsStatics = new HashMap<>();
|
||||
} else {
|
||||
lhsStatics = JsonUtil.fromJson(new String(statisticBytes), new TypeToken<HashMap<String, StatisticsByDay>>() {
|
||||
}.getType());
|
||||
}
|
||||
byte[] countBytes = db.get(COUNT_KEY.getBytes());
|
||||
if (countBytes == null) {
|
||||
handleRecordCount = new HandleRecordCount();
|
||||
handleRecordCount.doCount = handleRecordCount.repoCount = handleRecordCount.userCount = 0;
|
||||
} else {
|
||||
handleRecordCount = JsonUtil.fromJson(new String(countBytes), HandleRecordCount.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToDB() throws RocksDBException {
|
||||
String statisticStr = JsonUtil.toJson(lhsStatics);
|
||||
db.put(STATISTICS_KEY.getBytes(), statisticStr.getBytes());
|
||||
String countStr = JsonUtil.toJson(handleRecordCount);
|
||||
db.put(COUNT_KEY.getBytes(), countStr.getBytes());
|
||||
}
|
||||
|
||||
public Map<String, Object> getLHSStatics(Map<String, String> postInfo) {
|
||||
if (postInfo.containsKey("day")) {
|
||||
return getLHSStaticsWithTime(postInfo);
|
||||
}
|
||||
HashMap<String, Object> respMap = new HashMap<>();
|
||||
for (String key : lhsStatics.keySet()) {
|
||||
respMap.put(key + "", JsonUtil.toJson(lhsStatics.get(key)));
|
||||
}
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, Object> getLHSStaticsWithTime(Map<String, String> postInfo) {
|
||||
long day = Long.parseLong(postInfo.get("day"));
|
||||
LOGGER.info(day);
|
||||
List<Integer> resolve = new ArrayList<>();
|
||||
List<Integer> delete = new ArrayList<>();
|
||||
List<Integer> register = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < day; i++) {
|
||||
resolve.add(0);
|
||||
delete.add(0);
|
||||
register.add(0);
|
||||
}
|
||||
|
||||
long interval = 24 * 60 * 60 * 1000; //一天
|
||||
long cur = System.currentTimeMillis();
|
||||
long startTime = cur - day * interval;
|
||||
// logger.info(JsonUtil.toJson(lhsStatics));
|
||||
try {
|
||||
for (String k : lhsStatics.keySet()) {
|
||||
long time = new SimpleDateFormat("yyyyMMdd").parse(k).getTime();
|
||||
if (time < startTime || time > cur) {
|
||||
continue;
|
||||
}
|
||||
int index = (int) ((time - startTime) / interval);
|
||||
//logger.info(index);
|
||||
resolve.set(index, resolve.get(index) + lhsStatics.get(k).resolveStatics);
|
||||
delete.set(index, delete.get(index) + lhsStatics.get(k).deleteStatics);
|
||||
register.set(index, register.get(index) + lhsStatics.get(k).registerStatics);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
HashMap<String, Object> respMap = new HashMap<>();
|
||||
respMap.put("resolve", resolve);
|
||||
respMap.put("delete", delete);
|
||||
respMap.put("register", register);
|
||||
|
||||
return respMap;
|
||||
}
|
||||
|
||||
public Map<String, Object> getLHSCount() {
|
||||
HashMap<String, Object> respMap = new HashMap<>();
|
||||
respMap.put("repoCount", String.valueOf(handleRecordCount.repoCount));
|
||||
respMap.put("doCount", String.valueOf(handleRecordCount.doCount));
|
||||
|
||||
ReadOptions readOptions = new ReadOptions().setPrefixSameAsStart(true);
|
||||
RocksIterator it1 = db.newIterator(readOptions);
|
||||
|
||||
ArrayList<String> doIDList = new ArrayList<>();
|
||||
it1.seek("86.5000.470/do.".getBytes());
|
||||
int total = 0;
|
||||
while (it1.isValid() && total < 10) {
|
||||
doIDList.add(new String(it1.key()));
|
||||
total++;
|
||||
it1.next();
|
||||
}
|
||||
it1.close();
|
||||
|
||||
RocksIterator it2 = db.newIterator(readOptions);
|
||||
ArrayList<String> repoIDList = new ArrayList<>();
|
||||
it2.seek("86.5000.470/doip.".getBytes());
|
||||
total = 0;
|
||||
while (it2.isValid() && total < 10) {
|
||||
repoIDList.add(new String(it2.key()));
|
||||
total++;
|
||||
it2.next();
|
||||
}
|
||||
|
||||
respMap.put("repoIDList", repoIDList);
|
||||
respMap.put("doIDList", doIDList);
|
||||
return respMap;
|
||||
|
||||
}
|
||||
|
||||
public Map<String, String> formData2Dic(String formData) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
if (formData == null || formData.trim().length() == 0) {
|
||||
return result;
|
||||
}
|
||||
final String[] items = formData.split("&");
|
||||
Arrays.stream(items).forEach(item -> {
|
||||
final String[] keyAndVal = item.split("=");
|
||||
if (keyAndVal.length == 2) {
|
||||
try {
|
||||
final String key = URLDecoder.decode(keyAndVal[0], "utf8");
|
||||
final String val = URLDecoder.decode(keyAndVal[1], "utf8");
|
||||
result.put(key, val);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static class HandleRecordCount {
|
||||
int repoCount;
|
||||
int doCount;
|
||||
int userCount;
|
||||
}
|
||||
}
|
146
src/main/java/org/bdware/server/nodecenter/CMNode.java
Normal file
146
src/main/java/org/bdware/server/nodecenter/CMNode.java
Normal file
@ -0,0 +1,146 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CMNode {
|
||||
private static final Logger LOGGER = LogManager.getLogger(CMNode.class);
|
||||
// public List<ContractDesp> contracts;
|
||||
public volatile List<ContractDesp> contracts; // 有路由信息
|
||||
public transient NodeCenterActions connection;
|
||||
public String pubKey;
|
||||
public String nodeName;
|
||||
public String udpID;
|
||||
public String ipPort;
|
||||
public int events;
|
||||
public String cimanager = "";
|
||||
public String peerID;
|
||||
public String masterAddress; // 这个节点如果作为master的地址,例如18010的这个值就是18011
|
||||
public int contractVersion;
|
||||
|
||||
public CMNode(NodeCenterActions nodeCenterController, String pubKey) {
|
||||
connection = nodeCenterController;
|
||||
this.pubKey = pubKey;
|
||||
}
|
||||
|
||||
// TODO nodeMangerPubkey
|
||||
public void updateContract(List<ContractDesp> cons, int version) {
|
||||
contracts = cons;
|
||||
contractVersion = version;
|
||||
for (ContractDesp desp : cons) {
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ContractMeta.toString(), desp.contractID, desp.contractName);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendEMsg(String msg) {
|
||||
connection.controller.sendEMsg(msg);
|
||||
}
|
||||
|
||||
public String formatContractName(String contractIDOrName) {
|
||||
if (null != contracts) {
|
||||
for (ContractDesp desp : contracts) {
|
||||
if (desp.contractID.equals(contractIDOrName)
|
||||
|| desp.contractName.equals(contractIDOrName)) {
|
||||
return desp.contractName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsContract(String contractIDOrName) {
|
||||
if (null != contracts) {
|
||||
for (ContractDesp desp : contracts) {
|
||||
if (desp.contractID.equals(contractIDOrName)
|
||||
|| desp.contractName.equals(contractIDOrName)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsEvent(String contractIDOrName, String event) {
|
||||
if (null != contracts) {
|
||||
for (ContractDesp desp : contracts) {
|
||||
if (desp.contractID.equals(contractIDOrName)
|
||||
|| desp.contractName.equals(contractIDOrName)) {
|
||||
if (desp.events.containsKey(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkAlive() {
|
||||
if (null == connection) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (!connection.controller.isOpen()) {
|
||||
LOGGER.info("node " + nodeName + "(" + pubKey.substring(0, 5) + ") may be offline!");
|
||||
// System.out.println(
|
||||
// new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
// .format(new Date(System.currentTimeMillis()))
|
||||
// + "[ADSP][CMNode] isAlive : "
|
||||
// + nodeName
|
||||
// + " not open!"
|
||||
// + "\n");
|
||||
return doubleCheckAlive();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("checking alive failed! " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doubleCheckAlive() {
|
||||
try {
|
||||
// Thread.sleep(3000L);
|
||||
Thread.sleep(500L);
|
||||
if (connection.controller.isOpen()) {
|
||||
LOGGER.info("node " + nodeName + "(" + pubKey.substring(0, 5) + ") is online!");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("checking alive failed! " + e.getMessage());
|
||||
}
|
||||
LOGGER.info("node " + nodeName + "(" + pubKey.substring(0, 5) + ") may be offline!");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeCIManager(String string) {
|
||||
LOGGER.debug("removeCIManager" + string);
|
||||
int start = this.cimanager.indexOf(string);
|
||||
if (start > 0) {
|
||||
this.cimanager =
|
||||
this.cimanager
|
||||
.substring(0, start)
|
||||
.concat(this.cimanager.substring(start + 130));
|
||||
}
|
||||
}
|
||||
|
||||
public void addCIManager(String string) {
|
||||
LOGGER.debug("addCIManager" + string);
|
||||
this.cimanager = this.cimanager.concat(" " + string);
|
||||
}
|
||||
|
||||
public void setCIManager(String string) {
|
||||
this.cimanager = string;
|
||||
}
|
||||
|
||||
public void setPeerID(String string) {
|
||||
this.peerID = string;
|
||||
}
|
||||
|
||||
public void setIpPort(String string) {
|
||||
this.ipPort = string;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
|
||||
public interface ContractExecutor {
|
||||
public void execute(String requestID, ResultCallback rc, String req);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
//NC
|
||||
public class ElectMasterTimeRecorder {
|
||||
public static Long startElect; //NC开始选举
|
||||
public static Long findNewMaster; //NC选出新master
|
||||
public static String newMaster;
|
||||
public static Long changeMasterFinish; //新master在NC上更新路由信息
|
||||
|
||||
public static Map nodeFindMasterCrash = new HashMap<String,Long>(); //nodeID,electMaster调用时间
|
||||
}
|
186
src/main/java/org/bdware/server/nodecenter/LogActions.java
Normal file
186
src/main/java/org/bdware/server/nodecenter/LogActions.java
Normal file
@ -0,0 +1,186 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.db.MultiIndexTimeDBUtilIntf;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.bdware.server.action.Action;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// CenterPortal的所有日志和统计数据
|
||||
public class LogActions {
|
||||
private static final Logger LOGGER = LogManager.getLogger(LogActions.class);
|
||||
|
||||
NCManagerAction managerAction;
|
||||
|
||||
public LogActions(NCManagerAction managerAction) {
|
||||
this.managerAction = managerAction;
|
||||
}
|
||||
|
||||
private void queryInternal(
|
||||
String actResp,
|
||||
MultiIndexTimeDBUtilIntf db,
|
||||
JsonObject json,
|
||||
ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
if (!json.has("start")) {
|
||||
ret.put("action", actResp);
|
||||
ret.put("data", new ArrayList<>());
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
return;
|
||||
}
|
||||
long startTime = json.get("start").getAsLong();
|
||||
long endTime = System.currentTimeMillis();
|
||||
if (json.has("end")) {
|
||||
endTime = json.get("end").getAsLong();
|
||||
}
|
||||
String[] category = new String[]{null};
|
||||
if (json.has("category")) {
|
||||
category = json.get("category").getAsString().split(",");
|
||||
}
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
for (String str : category) {
|
||||
List<JsonObject> array = db.queryByDateAsJson(str, startTime, endTime);
|
||||
if (str == null) data.put("primary", array);
|
||||
else data.put(str, array);
|
||||
}
|
||||
ret.put("action", actResp);
|
||||
ret.put("data", data);
|
||||
if (json.has("requestID")) {
|
||||
ret.put("responseID", json.get("requestID"));
|
||||
}
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[queryInternal:time]" + (end - start));
|
||||
}
|
||||
|
||||
private void countLogByCategoryInternal(
|
||||
String actResp,
|
||||
MultiIndexTimeDBUtilIntf db,
|
||||
JsonObject json,
|
||||
ResultCallback resultCallback) {
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
if (!json.has("start")) {
|
||||
ret.put("action", actResp);
|
||||
ret.put("data", new ArrayList<>());
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
return;
|
||||
}
|
||||
long startTime = json.get("start").getAsLong();
|
||||
long endTime = System.currentTimeMillis();
|
||||
if (json.has("end")) {
|
||||
endTime = json.get("end").getAsLong();
|
||||
}
|
||||
long interval = json.get("interval").getAsLong();
|
||||
String[] category = new String[]{null};
|
||||
if (json.has("category")) {
|
||||
category = json.get("category").getAsString().split(",");
|
||||
}
|
||||
JsonObject data = new JsonObject();
|
||||
for (String str : category) {
|
||||
JsonArray array = db.countInInterval(str, startTime, interval, endTime);
|
||||
if (str == null) data.add("primary", array);
|
||||
else data.add(str, array);
|
||||
}
|
||||
ret.put("action", actResp);
|
||||
ret.put("data", data);
|
||||
if (json.has("requestID")) {
|
||||
ret.put("responseID", json.get("requestID"));
|
||||
}
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 8, async = true)
|
||||
public void queryActionLog(JsonObject json, ResultCallback resultCallback) {
|
||||
queryInternal("onQueryActionLog", NodeCenterServer.nodeHttpLogDB, json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 8, async = true)
|
||||
public void countActionLogByCategory(JsonObject json, ResultCallback resultCallback) {
|
||||
countLogByCategoryInternal(
|
||||
"onCountActionLogByCategory", NodeCenterServer.nodeHttpLogDB, json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 8, async = true)
|
||||
public void queryCMLog(JsonObject json, ResultCallback resultCallback) {
|
||||
queryInternal("onQueryCMLog", NodeCenterServer.nodeTcpLogDB, json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 8, async = true)
|
||||
public void countCMLogByCategory(JsonObject json, ResultCallback resultCallback) {
|
||||
countLogByCategoryInternal(
|
||||
"onCountCMLogByCategory", NodeCenterServer.nodeTcpLogDB, json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 9)
|
||||
public void queryUserStat(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
long userList = KeyValueDBUtil.instance.getCount(NCTables.NodeUser.toString());
|
||||
long applylist = KeyValueDBUtil.instance.getCount(NCTables.ApplyRole.toString());
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onQueryUserStat\",\"userListCount\":"
|
||||
+ userList
|
||||
+ ",\"applyListCount\":"
|
||||
+ applylist
|
||||
+ "}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[queryUserStat:time]" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 9, async = true)
|
||||
public void listNodes(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
final String pubKey = managerAction.pubKey;
|
||||
LOGGER.debug("[listNodes] managerAction.pubKey " + pubKey);
|
||||
Map<String, CMNode> nodeinfos = NodeCenterActions.nodeInfos; // 所有在线节点?
|
||||
final Map<String, CMNode> cinodeinfos = new HashMap<>();
|
||||
List<String> dbnodes = KeyValueDBUtil.instance.getKeys(NCTables.NodesDB.toString());
|
||||
List<CMNode> onlineNodes = new ArrayList<>();
|
||||
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
if (KeyValueDBUtil.instance
|
||||
.getValue(NCTables.ConfigDB.toString(), "__CenterManager__")
|
||||
.contains(pubKey)) {
|
||||
LOGGER.debug("is center manager");
|
||||
LOGGER.debug("dbnodes " + dbnodes.toString());
|
||||
for (CMNode node : nodeinfos.values()) {
|
||||
LOGGER.debug("Offline node " + node.nodeName + node.pubKey);
|
||||
if (dbnodes.contains(node.pubKey)) {
|
||||
dbnodes.remove(node.pubKey);
|
||||
LOGGER.debug("Delete Online node " + node.pubKey);
|
||||
onlineNodes.add(node);
|
||||
}
|
||||
}
|
||||
ret.put("action", "onListNodes");
|
||||
ret.put("online", onlineNodes);
|
||||
ret.put("offline", dbnodes);
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, CMNode> entry : nodeinfos.entrySet()) {
|
||||
LOGGER.debug("Key = " + entry.getKey() + ", Value = " + entry.getValue());
|
||||
String cimanager = entry.getValue().cimanager;
|
||||
if (!cimanager.contains(pubKey)) {
|
||||
cinodeinfos.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
ret.put("action", "onListNodes");
|
||||
ret.put("online", cinodeinfos);
|
||||
ret.put("offline", new ArrayList<String>());
|
||||
// 合约管理员看不到offline nodes
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listNodes:time]" + (end - start));
|
||||
}
|
||||
|
||||
}
|
289
src/main/java/org/bdware/server/nodecenter/MasterActions.java
Normal file
289
src/main/java/org/bdware/server/nodecenter/MasterActions.java
Normal file
@ -0,0 +1,289 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.units.RequestCache;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MasterActions {
|
||||
private static final Logger LOGGER = LogManager.getLogger(MasterActions.class);
|
||||
// TODO 定期清缓存
|
||||
public static Map<String, RequestCache> requestCache =
|
||||
new ConcurrentHashMap<>(); // key is contractID,only for requestAll type contract
|
||||
|
||||
static {
|
||||
NodeCenterServer.scheduledThreadPool.scheduleWithFixedDelay(
|
||||
() -> {
|
||||
boolean flag = clearCache();
|
||||
if (flag) {
|
||||
try {
|
||||
Thread.sleep(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("sleeping is interrupted! " + e.getMessage());
|
||||
}
|
||||
}
|
||||
},
|
||||
0,
|
||||
0,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public NodeCenterFrameHandler controller;
|
||||
|
||||
public MasterActions(NodeCenterFrameHandler nodeCenterFrameHandler) {
|
||||
controller = nodeCenterFrameHandler;
|
||||
}
|
||||
|
||||
// judge the just online node whwther need to restart contracts,send the contracts'info
|
||||
/* public static void restartContracts(String nodePubKey){
|
||||
if(!NodeCenterActions.recoverMap.containsKey(nodePubKey)){
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("开始恢复节点" + NodeCenterActions.nodeinfos.get(nodePubKey).nodeName);
|
||||
|
||||
|
||||
// 恢复该节点的每一个集群运行的合约
|
||||
for (ContractRecord record : NodeCenterActions.recoverMap.get(nodePubKey).values()) {
|
||||
String contractID = record.contractID;
|
||||
if (record.recoverFlag != RecoverFlag.ToRecover)
|
||||
continue;
|
||||
|
||||
Map<String, String> req = new HashMap<String, String>();
|
||||
req.put("action", "queryUnitStatus");
|
||||
req.put("contractID", contractID);
|
||||
CMNode cmNode = NodeCenterActions.nodeinfos.get(nodePubKey);
|
||||
cmNode.connection.controller.sendMsg(gson.toJson(req));
|
||||
}
|
||||
}*/
|
||||
|
||||
/* @Action(async = true)
|
||||
public void onQueryUnitStatus(Map<String, String> args, final ResultCallback rc) {
|
||||
String mode = args.get("mode");
|
||||
String nodeID = args.get("nodeID");
|
||||
String contractID = args.get("contractID");
|
||||
ContractRecord record = NodeCenterActions.recoverMap.get(nodeID).get(contractID);
|
||||
logger.debug("节点" + NodeCenterActions.nodeinfos.get(args.get("nodeID")).nodeName + "崩溃前模式为" + mode);
|
||||
if(mode.equals(ContractUnitStatus.CommonMode.toString())){
|
||||
restartFromCommonMode(nodeID,record);
|
||||
}else if(mode.equals(ContractUnitStatus.StableMode.toString())){
|
||||
restartFromStableMode(nodeID,record);
|
||||
}
|
||||
}*/
|
||||
|
||||
// 当StableMode的节点的lastExeSeq和集群相差超过10时,通过CommonNode的恢复方式恢复
|
||||
/* @Action(async = true)
|
||||
public void restartByCommonNode(Map<String, String> args, final ResultCallback rc){
|
||||
String nodeID = args.get("nodeID");
|
||||
String contractID = args.get("contractID");
|
||||
ContractRecord record = NodeCenterActions.recoverMap.get(nodeID).get(contractID);
|
||||
restartFromCommonMode(nodeID,record);
|
||||
}*/
|
||||
|
||||
/*
|
||||
public static void restartFromCommonMode(String nodePubKey,ContractRecord record){
|
||||
logger.debug("从CommonMode中恢复:");
|
||||
|
||||
String contractID = record.contractID;
|
||||
|
||||
record.recoverFlag = RecoverFlag.Recovering;
|
||||
//先发消息,让恢复节点的该合约收到消息后只加入队列不dealRequests
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("action", "setRecovering");
|
||||
request.put("contractID",contractID);
|
||||
CMNode node = NodeCenterActions.nodeinfos.get(nodePubKey);
|
||||
node.connection.controller.sendMsg(gson.toJson(request));
|
||||
|
||||
//System.out.println("第一步 : [NodeCeterActions] restartContracts 开始处理合约 contractID=" + contractID);
|
||||
|
||||
if (NodeCenterActions.contractID2Members.containsKey(contractID)) {
|
||||
|
||||
// 在nodeinfos中找节点,该节点的pubKey在pubKeys中
|
||||
MultiPointContractInfo info = NodeCenterActions.contractID2Members.get(contractID);
|
||||
CMNode cmNode = null;
|
||||
for (int i = 0; i < info.members.size(); i++) {
|
||||
int size = info.members.size();
|
||||
String tempNodeID = info.members.get(record.order.incrementAndGet() % size);
|
||||
|
||||
if(NodeCenterActions.nodeinfos.containsKey(tempNodeID))
|
||||
cmNode = NodeCenterActions.nodeinfos.get(tempNodeID);
|
||||
else continue;
|
||||
|
||||
//System.out.println("查询节点 " + cmNode.nodeName);
|
||||
|
||||
if (cmNode != null && !cmNode.pubKey.equals(nodePubKey)) {
|
||||
//System.out.println("第二步 : [NodeCenterActions] 找到一个依赖恢复节点,其节点名为 " + cmNode.nodeName);
|
||||
|
||||
Map<String, String> req = new HashMap<String, String>();
|
||||
req.put("action", "dumpCurrentState");
|
||||
req.put("contractID", contractID);
|
||||
req.put("targetNodePubkey", nodePubKey);
|
||||
|
||||
// NC向该节点发送请求,让其存储自身当前状态并发给NC
|
||||
cmNode.connection.controller.sendMsg(gson.toJson(req));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(cmNode == null){
|
||||
logger.debug("[NodeCenterActions] Can't find a recover rely node!");
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO
|
||||
/* public static void restartFromStableMode(String nodePubkey,ContractRecord record){
|
||||
logger.debug("从StableMode中恢复:");
|
||||
|
||||
String contractID = record.contractID;
|
||||
record.recoverFlag = RecoverFlag.Recovering;
|
||||
//先发消息,让恢复节点的该合约收到消息后只加入队列不dealRequests
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("action", "setRecovering");
|
||||
request.put("contractID",contractID);
|
||||
request.put("mode", ContractUnitStatus.StableMode.toString());
|
||||
int lastExeSeq = NodeCenterActions.contractID2Members.get(contractID).ai.get() - 1;
|
||||
request.put("lastExeSeq",lastExeSeq + "");
|
||||
CMNode node = NodeCenterActions.nodeinfos.get(nodePubkey);
|
||||
node.connection.controller.sendMsg(gson.toJson(request));
|
||||
}*/
|
||||
|
||||
/* public static void unitModeCheck(String contractID){
|
||||
MultiPointContractInfo mpci = NodeCenterActions.contractID2Members.get(contractID);
|
||||
int total = 0,online = 0;
|
||||
for(String nodeId : mpci.members){
|
||||
if(NodeCenterActions.nodeinfos.containsKey(nodeId)){
|
||||
online++;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
|
||||
logger.debug("合约" + contractID + "的集群,上线节点有" + online + "个,总共节点有" + total + "个. Math.ceil(total / 2)=" + Math.ceil((double)total / 2) + " online > Math.ceil(total / 2)" + (online > Math.ceil(total / 2)) + " mpci.unitStatus=" + mpci.unitStatus);
|
||||
if(online > Math.ceil((double)total / 2) && mpci.unitStatus == ContractUnitStatus.StableMode){
|
||||
logger.debug("合约" + contractID + "的集群更改模式为" + ContractUnitStatus.CommonMode.toString());
|
||||
|
||||
Map<String, String> req = new HashMap<String, String>();
|
||||
req.put("action", "changeUnitStatus");
|
||||
req.put("contractID", contractID);
|
||||
req.put("mode",ContractUnitStatus.CommonMode.toString());
|
||||
for(String nodeId : mpci.members){
|
||||
if(NodeCenterActions.nodeinfos.containsKey(nodeId)){
|
||||
CMNode cmNode = NodeCenterActions.nodeinfos.get(nodeId);
|
||||
logger.debug("发消息给节点 " + cmNode.nodeName + " 设置合约" + contractID + "的集群模式为CommonMode");
|
||||
cmNode.connection.controller.sendMsg(gson.toJson(req));
|
||||
}
|
||||
}
|
||||
|
||||
mpci.unitStatus = ContractUnitStatus.CommonMode;
|
||||
}else if(online <= Math.ceil((double)total / 2) && mpci.unitStatus == ContractUnitStatus.CommonMode){
|
||||
logger.debug("合约" + contractID + "的集群更改模式为" + ContractUnitStatus.StableMode.toString());
|
||||
|
||||
Map<String, String> req = new HashMap<String, String>();
|
||||
req.put("action", "changeUnitStatus");
|
||||
req.put("contractID", contractID);
|
||||
req.put("mode",ContractUnitStatus.StableMode.toString());
|
||||
for(String nodeId : mpci.members){
|
||||
if(NodeCenterActions.nodeinfos.containsKey(nodeId)){
|
||||
CMNode cmNode = NodeCenterActions.nodeinfos.get(nodeId);
|
||||
Map<String,String> map = NodeCenterActions.recoverMap.get(nodeId).get(contractID).members;
|
||||
req.put("membersStr",JsonUtil.toJson(map)); //ContractRecord's members
|
||||
logger.debug("发消息给节点 " + cmNode.nodeName + " 设置合约" + contractID + "的集群模式为StableMode");
|
||||
cmNode.connection.controller.sendMsg(gson.toJson(req));
|
||||
}
|
||||
}
|
||||
|
||||
mpci.unitStatus = ContractUnitStatus.StableMode;
|
||||
|
||||
//将ContractRecord中members发给集群中节点
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
/* @Action(async = true)
|
||||
public void recoverFinish(Map<String, String> args, final ResultCallback rc) {
|
||||
ContractRecord cr = NodeCenterActions.recoverMap.get(args.get("nodeID")).get(args.get("contractID"));
|
||||
logger.debug("节点" + NodeCenterActions.nodeinfos.get(args.get("nodeID")).nodeName + "恢复完成!");
|
||||
if(cr.recoverFlag == RecoverFlag.Recovering)
|
||||
cr.recoverFlag = RecoverFlag.Fine;
|
||||
|
||||
logger.debug("恢复完成,需要检查合约" + args.get("contractID") + "的集群运行模式");
|
||||
unitModeCheck(args.get("contractID"));
|
||||
}*/
|
||||
|
||||
static boolean clearCache() {
|
||||
if (requestCache.isEmpty()) return true;
|
||||
|
||||
// final long time = System.currentTimeMillis() - 60000L; //60s
|
||||
// requestCache.entrySet()
|
||||
// .removeIf(
|
||||
// entry -> {
|
||||
// RequestCache cache = entry.getValue();
|
||||
// if (cache == null) return true;
|
||||
// return cache.getTime() < time;
|
||||
// });
|
||||
//
|
||||
// return false;
|
||||
|
||||
// 对每个合约,只保存最近RESERVED个请求
|
||||
// for(RequestCache rc : requestCache.values()){
|
||||
// int delete = rc.size() - RequestCache.RESERVED,count = 0;
|
||||
// if(delete > 0){
|
||||
// synchronized (rc){
|
||||
// for(Iterator<Integer> iterator = rc.requests.keySet().iterator();
|
||||
// iterator.hasNext(); ) {
|
||||
// Integer key = iterator.next();
|
||||
// if(count < delete){
|
||||
// iterator.remove();
|
||||
// count++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static RequestCache getCache(String contractID) {
|
||||
if (contractID != null) {
|
||||
RequestCache cache = requestCache.get(contractID);
|
||||
if (cache != null) return cache;
|
||||
else {
|
||||
LOGGER.debug("[NodeCenterActions] create requestcache:" + contractID);
|
||||
RequestCache reqc = new RequestCache();
|
||||
requestCache.put(contractID, reqc);
|
||||
return reqc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* @Action(async = true)
|
||||
public void sendCachedRequests(Map<String, String> args, final ResultCallback rc) {
|
||||
String contractID = args.get("contractID");
|
||||
int start = Integer.parseInt(args.get("start"));
|
||||
int end = Integer.parseInt(args.get("end"));
|
||||
|
||||
RequestCache cache = getCache(contractID);
|
||||
for(int i = start + 1;i < end;i++){
|
||||
if(cache == null || !cache.containsKey(i)){
|
||||
//this node crash
|
||||
String nodeID = args.get("nodeID");
|
||||
MasterActions.restartContracts(nodeID);
|
||||
}
|
||||
JsonObject jo = cache.get(i);
|
||||
if(jo == null){
|
||||
logger.debug("在NC中第 " + i + "个请求已经被清,无法发给恢复节点!");
|
||||
}else
|
||||
controller.sendMsg(JsonUtil.toJson(jo));
|
||||
|
||||
logger.debug("NC发送第 " + i + " " + jo.get("seq").getAsString() + " 个请求给Node");
|
||||
}
|
||||
}*/
|
||||
}
|
553
src/main/java/org/bdware/server/nodecenter/MetaIndexAction.java
Normal file
553
src/main/java/org/bdware/server/nodecenter/MetaIndexAction.java
Normal file
@ -0,0 +1,553 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.CharArraySet;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.WordlistLoader;
|
||||
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.StringField;
|
||||
import org.apache.lucene.document.TextField;
|
||||
import org.apache.lucene.index.*;
|
||||
import org.apache.lucene.queryparser.classic.ParseException;
|
||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.nodecenter.searchresult.ContractMeta;
|
||||
import org.bdware.server.nodecenter.searchresult.ResultModel;
|
||||
import org.wltea.analyzer.lucene.IKAnalyzer;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MetaIndexAction { // public static IndexWriter indexWriter;
|
||||
private static final Logger LOGGER = LogManager.getLogger(MetaIndexAction.class);
|
||||
// public static IndexSearcher indexSearcher;
|
||||
// public static TopDocs topDocs;
|
||||
// public static Query query;
|
||||
// public static QueryParser queryParser;
|
||||
// public static Analyzer analyzer;
|
||||
// public static IndexWriterConfig config;
|
||||
// public static List<Document> docList = new ArrayList<>();
|
||||
public static FSDirectory indexDir;
|
||||
public static Integer PAGE_SIZE = 10;
|
||||
public static Integer page;
|
||||
public static boolean isEmpty = false;
|
||||
public static NodeCenterFrameHandler controller;
|
||||
// public MetaIndexAction(NodeCenterFrameHandler nodeCenterFrameHandler) {
|
||||
// controller = nodeCenterFrameHandler;
|
||||
// }
|
||||
private static IndexWriter indexWriter;
|
||||
|
||||
static {
|
||||
initIndex();
|
||||
}
|
||||
|
||||
private static void initIndex() {
|
||||
try {
|
||||
File dir = new File("./NodeCenterDB/MetaIndex");
|
||||
if (!dir.exists()) {
|
||||
LOGGER.info("make metaIndex dir ");
|
||||
dir.mkdirs();
|
||||
isEmpty = true;
|
||||
}
|
||||
indexDir = FSDirectory.open(Paths.get(dir.toURI()));
|
||||
// Analyzer analyzer = new StandardAnalyzer();
|
||||
Analyzer analyzer = new IKAnalyzer();
|
||||
IndexWriterConfig config = new IndexWriterConfig(analyzer);
|
||||
indexWriter = new IndexWriter(indexDir, config);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateContractsIndex(List<ContractDesp> contracts, ResultCallback rc)
|
||||
throws IOException {
|
||||
IndexReader indexReader = null;
|
||||
for (ContractDesp thisDesp : contracts) {
|
||||
JsonObject req = new JsonObject();
|
||||
if (!isEmpty) {
|
||||
try {
|
||||
indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
LOGGER.debug(thisDesp.contractName + "--> try to index");
|
||||
Query query = new TermQuery(new Term("contractID", thisDesp.contractID));
|
||||
TopDocs docs = indexSearcher.search(query, 10);
|
||||
LOGGER.debug(docs.scoreDocs);
|
||||
if (null != thisDesp.contractName && (docs.scoreDocs == null || docs.scoreDocs.length == 0)) {
|
||||
req.addProperty("action", "requestReadMe");
|
||||
req.addProperty("contractID", thisDesp.contractID);
|
||||
rc.onResult(req.toString());
|
||||
LOGGER.info("contract " + thisDesp.contractName + " --> actually to index");
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("getting index failed! " + e.getMessage());
|
||||
}
|
||||
}
|
||||
req.addProperty("action", "requestReadMe");
|
||||
req.addProperty("contractID", thisDesp.contractID);
|
||||
rc.onResult(req.toString());
|
||||
LOGGER.info("contract " + thisDesp.contractName + " --> actually to index");
|
||||
}
|
||||
if (null != indexReader) {
|
||||
indexReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String accuSearch(String keyword) {
|
||||
try {
|
||||
DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
Term t = new Term("contractID", keyword);
|
||||
Query query = new TermQuery(t);
|
||||
TopDocs docs = indexSearcher.search(query, 10);
|
||||
return docs.scoreDocs.length + "";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static void delIndexbyCID(JsonObject jo) {
|
||||
try {
|
||||
if (!jo.has("contractID")) return;
|
||||
String contractID = jo.get("contractID").getAsString();
|
||||
LOGGER.info("contractID:" + contractID + "-->actually to delete");
|
||||
indexWriter.deleteDocuments(new Term("contractID", contractID));
|
||||
indexWriter.commit();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void delIndexbyOwner(JsonObject jo) {
|
||||
try {
|
||||
if (!jo.has("owner")) return;
|
||||
String owner = jo.get("owner").getAsString();
|
||||
LOGGER.info("owner:" + owner + "-->actually to delete");
|
||||
indexWriter.deleteDocuments(new Term("owner", owner));
|
||||
indexWriter.commit();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String search(JsonObject searchReq) {
|
||||
try {
|
||||
if (!searchReq.has("searchType")) {
|
||||
return "missing arguments";
|
||||
}
|
||||
switch (searchReq.get("searchType").getAsString()) {
|
||||
case "getMetabyCID":
|
||||
return getMetabyCID(searchReq);
|
||||
case "getMetabyOwner":
|
||||
return getMetabyOwner(searchReq);
|
||||
case "getMetabyPubkey":
|
||||
return getMetabyPubkey(searchReq);
|
||||
case "getMetabyReadme":
|
||||
return getMetabyReadme(searchReq);
|
||||
default:
|
||||
return "no such search type";
|
||||
}
|
||||
// if (searchReq != null) {
|
||||
// logger.info(searchReq.get("pubkey").getAsString() + "---->start
|
||||
// search");
|
||||
// DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
// IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
// BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
|
||||
// reandler(searchReq, queryBuilder);
|
||||
// BooleanQuery searchQuery = queryBuilder.build();
|
||||
// TopDocs docs = indexSearcher.search(searchQuery, 10);
|
||||
// return docs.scoreDocs.length + "";
|
||||
// }
|
||||
// else return "0";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMetabyReadme(JsonObject jo) {
|
||||
try {
|
||||
if (!jo.has("keyword")) return "missing arguments: keyword";
|
||||
|
||||
if (!jo.has("page")) page = 1;
|
||||
else page = jo.get("page").getAsInt();
|
||||
if (page <= 0) page = 1;
|
||||
if (jo.has("pageSize")) PAGE_SIZE = jo.get("pageSize").getAsInt();
|
||||
String keyword = jo.get("keyword").getAsString();
|
||||
// Analyzer analyzer = new StandardAnalyzer();
|
||||
Analyzer analyzer = new IKAnalyzer();
|
||||
QueryParser queryParser = new QueryParser("readmeStr", analyzer);
|
||||
Query rmQuery = queryParser.parse(keyword);
|
||||
|
||||
DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
TopDocs docs = indexSearcher.search(rmQuery, 1000);
|
||||
// Document document = null ;
|
||||
// if (docs.scoreDocs!=null&& docs.scoreDocs.length>0) {
|
||||
// document = indexSearcher.doc(docs.scoreDocs[0].doc);
|
||||
// ContractMeta contractMeta = new ContractMeta();
|
||||
// contractMeta.setContractID(document.get("contractID"));
|
||||
// contractMeta.setOwner(document.get("owner"));
|
||||
// contractMeta.setPubkey(document.get("pubkey"));
|
||||
// contractMeta.setReadmeStr(document.get("readmeStr"));
|
||||
// String rs = JsonUtil.toJson(contractMeta);
|
||||
// return rs;
|
||||
// }
|
||||
ResultModel resultModel = null;
|
||||
if (docs.scoreDocs != null && docs.scoreDocs.length > 0)
|
||||
resultModel = paginate(docs, indexReader);
|
||||
if (resultModel != null) {
|
||||
String rs = JsonUtil.toJson(resultModel);
|
||||
return rs;
|
||||
}
|
||||
return "not found";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMetabyPubkey(JsonObject jo) {
|
||||
try {
|
||||
if (!jo.has("pubkey")) return "missing arguments: pubkey";
|
||||
|
||||
if (!jo.has("page")) page = 1;
|
||||
else page = jo.get("page").getAsInt();
|
||||
if (page <= 0) page = 1;
|
||||
|
||||
String pubkey = jo.get("pubkey").getAsString();
|
||||
DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
Query query = new TermQuery(new Term("pubkey", pubkey));
|
||||
TopDocs docs = indexSearcher.search(query, 10);
|
||||
// Document document = null;
|
||||
// if (docs.scoreDocs!=null&& docs.scoreDocs.length>0) {
|
||||
// document = indexSearcher.doc(docs.scoreDocs[0].doc);
|
||||
// ContractMeta contractMeta = new ContractMeta();
|
||||
// contractMeta.setContractID(document.get("contractID"));
|
||||
// contractMeta.setOwner(document.get("owner"));
|
||||
// contractMeta.setPubkey(document.get("pubkey"));
|
||||
// contractMeta.setReadmeStr(document.get("readmeStr"));
|
||||
// String rs = JsonUtil.toJson(contractMeta);
|
||||
// return rs;
|
||||
// }
|
||||
ResultModel resultModel = null;
|
||||
if (docs.scoreDocs != null && docs.scoreDocs.length > 0)
|
||||
resultModel = paginate(docs, indexReader);
|
||||
if (resultModel != null) {
|
||||
String rs = JsonUtil.toJson(resultModel);
|
||||
return rs;
|
||||
}
|
||||
return "not found";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMetabyCID(JsonObject jo) {
|
||||
System.out.println("getMetabyCID" + jo.toString());
|
||||
try {
|
||||
if (!jo.has("contractID")) return "missing arguments: contractID";
|
||||
|
||||
if (!jo.has("page")) page = 1;
|
||||
else page = jo.get("page").getAsInt();
|
||||
if (page <= 0) page = 1;
|
||||
|
||||
String contractID = jo.get("contractID").getAsString();
|
||||
DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
Query query = new TermQuery(new Term("contractID", contractID));
|
||||
TopDocs docs = indexSearcher.search(query, 10);
|
||||
// Document document = null;
|
||||
// if (docs.scoreDocs!=null&& docs.scoreDocs.length>0) {
|
||||
// document = indexSearcher.doc(docs.scoreDocs[0].doc);
|
||||
// ContractMeta contractMeta = new ContractMeta();
|
||||
// contractMeta.setContractID(document.get("contractID"));
|
||||
// contractMeta.setOwner(document.get("owner"));
|
||||
// contractMeta.setPubkey(document.get("pubkey"));
|
||||
// contractMeta.setReadmeStr(document.get("readmeStr"));
|
||||
// String rs = JsonUtil.toJson(contractMeta);
|
||||
// return rs;
|
||||
// }
|
||||
ResultModel resultModel = null;
|
||||
if (docs.scoreDocs != null && docs.scoreDocs.length > 0)
|
||||
resultModel = paginate(docs, indexReader);
|
||||
if (resultModel != null) {
|
||||
String rs = JsonUtil.toJson(resultModel);
|
||||
return rs;
|
||||
}
|
||||
return "not found";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMetabyOwner(JsonObject jo) {
|
||||
try {
|
||||
if (!jo.has("owner")) return "missing arguments: owner";
|
||||
|
||||
if (!jo.has("page")) page = 1;
|
||||
else page = jo.get("page").getAsInt();
|
||||
if (page <= 0) page = 1;
|
||||
if (jo.has("pageSize")) PAGE_SIZE = jo.get("pageSize").getAsInt();
|
||||
String owner = jo.get("owner").getAsString();
|
||||
DirectoryReader indexReader = DirectoryReader.open(indexDir);
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
Query query = new TermQuery(new Term("owner", owner));
|
||||
TopDocs docs = indexSearcher.search(query, 1000);
|
||||
// Document document = null;
|
||||
// if (docs.scoreDocs!=null&& docs.scoreDocs.length>0) {
|
||||
// document = indexSearcher.doc(docs.scoreDocs[0].doc);
|
||||
// ContractMeta contractMeta = new ContractMeta();
|
||||
// contractMeta.setContractID(document.get("contractID"));
|
||||
// contractMeta.setOwner(document.get("owner"));
|
||||
// contractMeta.setPubkey(document.get("pubkey"));
|
||||
// contractMeta.setReadmeStr(document.get("readmeStr"));
|
||||
// String rs = JsonUtil.toJson(contractMeta);
|
||||
// return rs;
|
||||
// }
|
||||
ResultModel resultModel = null;
|
||||
if (docs.scoreDocs != null && docs.scoreDocs.length > 0)
|
||||
resultModel = paginate(docs, indexReader);
|
||||
if (resultModel != null) {
|
||||
String rs = JsonUtil.toJson(resultModel);
|
||||
return rs;
|
||||
}
|
||||
return "not found";
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
return bo.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static void reqHandler(JsonObject req, BooleanQuery.Builder query)
|
||||
throws ParseException {
|
||||
if (req.get("contractID").getAsString() != null) {
|
||||
query.add(
|
||||
new FuzzyQuery(new Term("contractID", req.get("contractID").getAsString())),
|
||||
BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
if (req.get("owner").getAsString() != null) {
|
||||
query.add(
|
||||
new FuzzyQuery(new Term("owner", req.get("owner").getAsString())),
|
||||
BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
if (req.get("pubkey").getAsString() != null) {
|
||||
query.add(
|
||||
new PrefixQuery(new Term("pubkey", req.get("pubkey").getAsString())),
|
||||
BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
if (req.get("readmeStr").getAsString() != null) {
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
QueryParser queryParser = new QueryParser("name", analyzer);
|
||||
Query rmQuery = queryParser.parse(req.get("readmeStr").getAsString());
|
||||
query.add(rmQuery, BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultModel paginate(TopDocs docs, IndexReader reader) throws IOException {
|
||||
ResultModel resultModel = new ResultModel();
|
||||
Integer start = (page - 1) * PAGE_SIZE;
|
||||
Integer end = page * PAGE_SIZE;
|
||||
resultModel.setContractCount(docs.totalHits.value);
|
||||
ScoreDoc[] scoreDocs = docs.scoreDocs;
|
||||
List<ContractMeta> contractMetaList = new ArrayList<>();
|
||||
if (scoreDocs != null) {
|
||||
for (int i = start; i < scoreDocs.length && i < end; i++) {
|
||||
Document document = reader.document(scoreDocs[i].doc);
|
||||
ContractMeta contractMeta = new ContractMeta();
|
||||
contractMeta.setContractID(document.get("contractID"));
|
||||
contractMeta.setStatus(document.get("status"));
|
||||
contractMeta.setOwner(document.get("owner"));
|
||||
contractMeta.setPubkey(document.get("pubkey"));
|
||||
contractMeta.setReadmeStr(document.get("readmeStr"));
|
||||
contractMeta.setNodeAddr(document.get("nodeAddr"));
|
||||
contractMeta.setPngUrl(document.get("pngUrl"));
|
||||
contractMeta.setName(document.get("name"));
|
||||
contractMeta.setDoi(document.get("doi"));
|
||||
contractMeta.setBuildTime(Long.parseLong(document.get("buildTime")));
|
||||
contractMeta.setDoip("DOIP://86.470.5000/" + document.get("name"));
|
||||
contractMetaList.add(contractMeta);
|
||||
}
|
||||
}
|
||||
resultModel.setContractMetaList(contractMetaList);
|
||||
resultModel.setCurPage(page);
|
||||
Long pageCount =
|
||||
docs.totalHits.value % PAGE_SIZE > 0
|
||||
? (docs.totalHits.value) / PAGE_SIZE + 1
|
||||
: (docs.totalHits.value) / PAGE_SIZE;
|
||||
resultModel.setPageCount(pageCount);
|
||||
return resultModel;
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public synchronized void onRequestReadMe(JsonObject json, ResultCallback rc)
|
||||
throws IOException {
|
||||
// try {
|
||||
// Thread.sleep(2000);
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
CMNode node = NodeCenterActions.nodeInfos.get(controller.pubKey);
|
||||
String nodeAddr = getNodeAddr(node.masterAddress);
|
||||
String name = json.get("name").getAsString();
|
||||
// /DOIP/Hello1/assets/logo.png
|
||||
// String nodeAddr="127.0.0.1:21030";
|
||||
String pngUrl = "http://" + nodeAddr + "/DOIP/" + name + "/assets/logo.png";
|
||||
System.out.println(
|
||||
"node.masterAddress: "
|
||||
+ node.masterAddress
|
||||
+ "=========="
|
||||
+ "nodeAddr: "
|
||||
+ nodeAddr);
|
||||
System.out.println("name: " + name + "pngUrl: " + pngUrl);
|
||||
String contractID = json.get("contractID").getAsString();
|
||||
String status = json.get("status").getAsString();
|
||||
String owner = json.get("owner").getAsString();
|
||||
String pubkey = json.get("pubkey").getAsString();
|
||||
String readmeStr = json.get("readmeStr").getAsString();
|
||||
String doi = json.get("doi").getAsString();
|
||||
String buildTime = String.valueOf(json.get("buildTime").getAsLong());
|
||||
Document document = new Document();
|
||||
document.add(new StringField("contractID", contractID, Field.Store.YES));
|
||||
document.add(new StringField("status", status, Field.Store.YES));
|
||||
document.add(new StringField("owner", owner, Field.Store.YES));
|
||||
document.add(new StringField("pubkey", pubkey, Field.Store.YES));
|
||||
document.add(new TextField("readmeStr", readmeStr, Field.Store.YES));
|
||||
document.add(new StringField("nodeAddr", nodeAddr, Field.Store.YES));
|
||||
document.add(new StringField("pngUrl", pngUrl, Field.Store.YES));
|
||||
document.add(new StringField("name", name, Field.Store.YES));
|
||||
document.add(new StringField("doi", doi, Field.Store.YES));
|
||||
document.add(new StringField("buildTime", buildTime, Field.Store.YES));
|
||||
LOGGER.info("Index Meta:" + contractID + " str:" + readmeStr);
|
||||
LOGGER.info("name:" + name + "=>" + "doi:" + doi + "=>" + "buildTime:" + buildTime);
|
||||
indexWriter.addDocument(document);
|
||||
indexWriter.commit();
|
||||
isEmpty = false;
|
||||
// TODO @fanbo 更新lucene
|
||||
}
|
||||
|
||||
private String getNodeAddr(String masterAddress) {
|
||||
String[] temp = masterAddress.split(":");
|
||||
temp[1] = String.valueOf(Integer.parseInt(temp[1]) - 1);
|
||||
String nodeAddr = temp[0] + ":" + temp[1];
|
||||
return nodeAddr;
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void getMetabyReadme(JsonObject json, ResultCallback rc) {
|
||||
String result = getMetabyReadme(json);
|
||||
JsonObject object = new JsonObject();
|
||||
if (json.has("requestID")) object.add("responseID", json.get("requestID"));
|
||||
System.out.println("zzzResult" + result);
|
||||
object.add("result", JsonParser.parseString(result));
|
||||
object.addProperty("action", "getMetabyReadme");
|
||||
rc.onResult(object.toString());
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void segmentWord(JsonObject json, ResultCallback rc) throws IOException {
|
||||
//Analyzer analyzer = new IKAnalyzer(true);
|
||||
CharArraySet stopWords = CharArraySet.unmodifiableSet(WordlistLoader.getWordSet(new InputStreamReader(Objects.requireNonNull(MetaIndexAction.class.getClassLoader().getResourceAsStream(
|
||||
"org/bdware/server/stopwords.txt")), StandardCharsets.UTF_8)));
|
||||
Analyzer analyzer = new SmartChineseAnalyzer(stopWords);
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
String words = "我喜欢区块链,我想试用一下这个,我是做大数据处理的,我是科技局的管理员"; // 从json拿
|
||||
TokenStream stream = null;
|
||||
if (json.has("requestID")) object.add("responseID", json.get("requestID"));
|
||||
try {
|
||||
stream = analyzer.tokenStream("myfield", words);
|
||||
CharTermAttribute charTermAtt = stream.addAttribute(CharTermAttribute.class);
|
||||
stream.reset();
|
||||
int count = 0;
|
||||
while (stream.incrementToken()) {
|
||||
object.addProperty("" + count++, charTermAtt.toString());
|
||||
System.out.println(charTermAtt.toString());
|
||||
}
|
||||
stream.end();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
rc.onResult(object.toString());
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void getMetabyCID(JsonObject json, ResultCallback rc) {
|
||||
String result = getMetabyCID(json);
|
||||
JsonObject object = new JsonObject();
|
||||
if (json.has("requestID")) object.add("responseID", json.get("requestID"));
|
||||
object.add("result", JsonParser.parseString(result));
|
||||
object.addProperty("action", "getMetabyCID");
|
||||
rc.onResult(object.toString());
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void getMetabyOwner(JsonObject json, ResultCallback rc) {
|
||||
String result = getMetabyOwner(json);
|
||||
JsonObject object = new JsonObject();
|
||||
if (json.has("requestID")) object.add("responseID", json.get("requestID"));
|
||||
object.add("result", JsonParser.parseString(result));
|
||||
object.addProperty("action", "getMetabyOwner");
|
||||
rc.onResult(object.toString());
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void getMetabyPubkey(JsonObject json, ResultCallback rc) {
|
||||
String result = getMetabyPubkey(json);
|
||||
JsonObject object = new JsonObject();
|
||||
if (json.has("requestID")) object.add("responseID", json.get("requestID"));
|
||||
object.add("result", JsonParser.parseString(result));
|
||||
object.addProperty("action", "getMetabyPubkey");
|
||||
rc.onResult(object.toString());
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void delIndexbyCID(JsonObject json, ResultCallback rc) {
|
||||
delIndexbyCID(json);
|
||||
}
|
||||
|
||||
@Action(async = true, userPermission = 1L)
|
||||
public void delIndexbyOwner(JsonObject json, ResultCallback rc) {
|
||||
delIndexbyOwner(json);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import org.bdware.sc.bean.ContractExecType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class MultiPointContractInfo {
|
||||
public List<String> members; //pubKey
|
||||
public ContractExecType type;
|
||||
AtomicInteger ai = new AtomicInteger();
|
||||
|
||||
public transient ContractExecutor rcf;
|
||||
|
||||
public String getNextSeq(){
|
||||
System.out.println("MultiPointContractInfo获得下一个序号" + (ai.get() + 1));
|
||||
return ai.getAndIncrement() + "";
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.bean.OtherNCInfo;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
import org.zz.gmhelper.SM2Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NCClientActions {
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCClientActions.class);
|
||||
private final NCClientHandler handler;
|
||||
|
||||
public NCClientActions(NCClientHandler h) {
|
||||
handler = h;
|
||||
}
|
||||
|
||||
@Action
|
||||
public void onSessionID(JsonObject json, ResultCallback cb) {
|
||||
LOGGER.info("[NCClientActions] onSessionID : ");
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
LOGGER.debug("[onSessionID]:" + json.toString());
|
||||
map.put("action", "getNCConnectPermission");
|
||||
map.put("id", OtherNCProxy.instance.sm2.getPublicKeyStr());
|
||||
byte[] signature = "no signature".getBytes();
|
||||
try {
|
||||
signature = SM2Util.sign(OtherNCProxy.instance.sm2.getPrivateKeyParameter(), (OtherNCProxy.instance.sm2.getPublicKeyStr() + json.get("session").getAsString())
|
||||
.getBytes());
|
||||
} catch (CryptoException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
map.put("signature", ByteUtils.toHexString(signature));
|
||||
sendMsg(JsonUtil.toJson(map));
|
||||
}
|
||||
|
||||
@Action
|
||||
public void onGetNCConnectPermission(JsonObject json, ResultCallback resultCallback) {
|
||||
LOGGER.info("[NCClientActions] onGetNCConnectPermission : ");
|
||||
|
||||
if (json.get("data").getAsString().equals("success")) {
|
||||
handler.hasPermission = true;
|
||||
LOGGER.info("[NCClientActions] onGetNCConnectPermission : permission true");
|
||||
}
|
||||
}
|
||||
|
||||
@Action
|
||||
public void receiveUpdate(JsonObject json, ResultCallback resultCallback) {
|
||||
LOGGER.info("[NCClientActions] receiveUpdate : ");
|
||||
List<OtherNCInfo> info = new ArrayList<OtherNCInfo>();
|
||||
|
||||
if (json.has("empty")) {
|
||||
LOGGER.info("receive from NC ,do not have any cp.");
|
||||
} else {
|
||||
info = JsonUtil.fromJson(json.get("contracts").getAsString(), new TypeToken<List<OtherNCInfo>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
LOGGER.info(JsonUtil.toJson(info));
|
||||
|
||||
String id = json.get("id").getAsString();
|
||||
OtherNCProxy.instance.updateOtherNCInfo(id, info);
|
||||
|
||||
String add = json.get("address").getAsString();
|
||||
LOGGER.info("[NCClientActinos] close connect " + add);
|
||||
OtherNCProxy.instance.connList.get(add).close();
|
||||
}
|
||||
|
||||
public void sendMsg(String str) {
|
||||
try {
|
||||
handler.sendMsg(str);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
114
src/main/java/org/bdware/server/nodecenter/NCClientHandler.java
Normal file
114
src/main/java/org/bdware/server/nodecenter/NCClientHandler.java
Normal file
@ -0,0 +1,114 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.ActionExecutor;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class NCClientHandler extends SimpleChannelInboundHandler<Object> {
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCClientHandler.class);
|
||||
static ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
public boolean hasPermission; //是否在目标NC上有权限
|
||||
public NCClientActions actions;
|
||||
Channel channel;
|
||||
ActionExecutor<ResultCallback, JsonObject> ae;
|
||||
ChannelHandlerContext ctx;
|
||||
private boolean isConnected;
|
||||
|
||||
public NCClientHandler() {
|
||||
actions = new NCClientActions(this);
|
||||
ae = new ActionExecutor<>(executorService, actions);
|
||||
isConnected = false;
|
||||
hasPermission = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
channel = ctx.channel();
|
||||
isConnected = true;
|
||||
this.ctx = ctx;
|
||||
Map<String, String> getSession = new HashMap<>();
|
||||
getSession.put("action", "getSessionID");
|
||||
sendMsg(JsonUtil.toJson(getSession));
|
||||
LOGGER.debug("[NCClientHandler] getSessionID:" + JsonUtil.toJson(getSession));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
isConnected = false;
|
||||
hasPermission = false;
|
||||
try {
|
||||
channel.close();
|
||||
channel = null;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendMsg(String msg) {
|
||||
channel.writeAndFlush(Unpooled.wrappedBuffer(msg.getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
ByteBuf bb = (ByteBuf) msg;
|
||||
try {
|
||||
final JsonObject arg =
|
||||
new JsonParser()
|
||||
.parse(new InputStreamReader(new ByteBufInputStream(bb)))
|
||||
.getAsJsonObject();
|
||||
if (arg.has("action")) {
|
||||
final String action = arg.get("action").getAsString();
|
||||
ae.handle(
|
||||
action,
|
||||
arg,
|
||||
new ResultCallback() {
|
||||
@Override
|
||||
public void onResult(String str) {
|
||||
sendMsg(str);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} catch (java.lang.IllegalArgumentException e) {
|
||||
LOGGER.debug("[NCClientHandler] can't handle action:" + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
System.err.println("[NCClientHandler] catchException");
|
||||
cause.printStackTrace();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
isConnected = false;
|
||||
if (channel != null) channel.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
channel = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return ctx != null && ctx.channel().isOpen();
|
||||
}
|
||||
}
|
@ -0,0 +1,210 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class NCElectMasterUtil {
|
||||
public static final Map<String, ElectInfo> electInfos = new ConcurrentHashMap<>(); //key is contractID
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCElectMasterUtil.class);
|
||||
|
||||
public static class ElectInfo {
|
||||
final long delay = 5000;
|
||||
final AtomicBoolean startElect = new AtomicBoolean(false);
|
||||
String formerMaster;
|
||||
String uniNumber;
|
||||
long lastTime = System.currentTimeMillis();
|
||||
int onlineNum; //除旧的master之外的在线节点数
|
||||
String contractID;
|
||||
String mems; //执行这个合约的所有节点的pubKey
|
||||
private Map<String, Integer> nodeID2LastExe = new ConcurrentHashMap<>(); //key is nodeID
|
||||
private Timer timer;
|
||||
|
||||
|
||||
public ElectInfo(String m, String con, String members, String uni) {
|
||||
formerMaster = m;
|
||||
contractID = con;
|
||||
mems = members;
|
||||
uniNumber = uni;
|
||||
String[] mem = members.split(",");
|
||||
|
||||
/* try {
|
||||
Thread.sleep(2000); //让NC发现崩溃节点
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
|
||||
for (String memID : mem) {
|
||||
if (memID == null || memID.length() == 0)
|
||||
continue;
|
||||
|
||||
if (NodeCenterActions.nodeInfos.containsKey(memID) && !memID.equals(formerMaster)) {
|
||||
onlineNum++;
|
||||
}
|
||||
}
|
||||
NodeCenterServer.scheduledThreadPool.scheduleWithFixedDelay(
|
||||
() -> {
|
||||
// cancel the election if no nodes find the master's crash in delay + 2 seconds
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd.HH:mm:ss.SSS");
|
||||
if (System.currentTimeMillis() - lastTime > (delay + 15000)) {
|
||||
LOGGER.info("lastTime=" + df.format(lastTime) + " cancel the election");
|
||||
cancel();
|
||||
}
|
||||
// start timeout election
|
||||
// if (electInfos.containsKey(contractID) && nodeID2LastExe.size() == onlineNum) {
|
||||
// elect();
|
||||
// }
|
||||
},
|
||||
delay + 1500,
|
||||
delay + 1500,
|
||||
TimeUnit.MILLISECONDS);
|
||||
//timer.schedule(task, dealy + 2000);
|
||||
|
||||
LOGGER.info("new election of contract " + contractID + " is added to electInfos, " +
|
||||
onlineNum + " node is online");
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if (electInfos.containsKey(contractID)) {
|
||||
electInfos.remove(contractID);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void put(String nodeID, int lastExe, String master, String mem2, String uniNum) {
|
||||
LOGGER.info("put nodeID=" + nodeID);
|
||||
|
||||
//确保该合约某时只能有一个选举,其他的选举请求被忽略
|
||||
if (!master.equals(formerMaster)) {
|
||||
LOGGER.debug("[NCElectMasterUtil] master error!");
|
||||
return;
|
||||
}
|
||||
if (nodeID.equals(formerMaster)) {
|
||||
LOGGER.debug("former master voted,error!");
|
||||
return;
|
||||
}
|
||||
if (master.equals("null")) {
|
||||
LOGGER.info("uniNum=" + uniNum + " uniNumber=" + uniNumber);
|
||||
if (!uniNum.equals(uniNumber)) {
|
||||
LOGGER.debug("already has re-elect process when master is null");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
//认为是一个新的选举,之前的作废
|
||||
if (now - lastTime > delay) {
|
||||
LOGGER.info("[NCElectMasterUtil] time error!");
|
||||
cancel();
|
||||
synchronized (electInfos) {
|
||||
//electInfos.remove(contractID);
|
||||
NCElectMasterUtil.electInfos.put(contractID, new ElectInfo(master, contractID, mem2, uniNum));
|
||||
ElectInfo eleInfo = electInfos.get(contractID);
|
||||
eleInfo.put(nodeID, lastExe, master, mem2, uniNum);
|
||||
}
|
||||
return;
|
||||
}
|
||||
lastTime = now;
|
||||
nodeID2LastExe.put(nodeID, lastExe);
|
||||
|
||||
LOGGER.info("[ElectInfo] 加入合约 " + contractID + " 的选举信息节点" + nodeID.substring(0, 5));
|
||||
|
||||
if (nodeID2LastExe.size() == onlineNum) {
|
||||
cancel();
|
||||
elect();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void elect() {
|
||||
LOGGER.info("[ElectInfo] 开始选举");
|
||||
|
||||
ElectMasterTimeRecorder.startElect = System.currentTimeMillis();
|
||||
|
||||
synchronized (startElect) {
|
||||
startElect.set(true);
|
||||
}
|
||||
|
||||
//更新路由信息,这个合约的master暂时为null
|
||||
if (NodeCenterActions.nodeInfos.containsKey(formerMaster)) {
|
||||
CMNode node = NodeCenterActions.nodeInfos.get(formerMaster);
|
||||
if (node != null) {
|
||||
synchronized (node) {
|
||||
for (ContractDesp cd : node.contracts) {
|
||||
if (cd.contractID.equals(contractID) || cd.contractName.equals(contractID)) {
|
||||
cd.setIsMaster(false);
|
||||
LOGGER.debug("设置节点 " + node.pubKey.substring(0, 5) + " 的合约 " + contractID + " isMaster=" + false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int maxExeSeq = Integer.MIN_VALUE;
|
||||
String newMaster = "";
|
||||
for (String id : nodeID2LastExe.keySet()) {
|
||||
if (nodeID2LastExe.get(id) > maxExeSeq) {
|
||||
newMaster = id;
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("[NCElectMasterUtil] 选举出新的master " + newMaster);
|
||||
|
||||
cancel();
|
||||
//electInfos.remove(contractID);
|
||||
|
||||
//通知新的master让它发起重连操作,并在所有节点重连成功之后开启master的恢复
|
||||
try {
|
||||
Thread.sleep(1500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LOGGER.info("开始计算需要连接新master的都有哪些节点:");
|
||||
StringBuilder onlineMems = new StringBuilder(); //不包含旧的master
|
||||
for (String memID : nodeID2LastExe.keySet()) {
|
||||
if (memID == null || memID.length() == 0)
|
||||
continue;
|
||||
|
||||
LOGGER.info("[NCElectMasterUtil] 查看节点 " + memID.substring(0, 5) + " 是否还在线");
|
||||
if (NodeCenterActions.nodeInfos.containsKey(memID)) {
|
||||
if (memID.equals(formerMaster))
|
||||
continue;
|
||||
|
||||
LOGGER.info("onlineMems中加入 " + memID.substring(0, 5));
|
||||
if (onlineMems.toString().equals("")) {
|
||||
onlineMems = new StringBuilder(memID);
|
||||
} else {
|
||||
onlineMems.append(",");
|
||||
onlineMems.append(memID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElectMasterTimeRecorder.findNewMaster = System.currentTimeMillis();
|
||||
ElectMasterTimeRecorder.newMaster = newMaster;
|
||||
|
||||
LOGGER.info("通知新的master让它发起重连操作 " + onlineMems);
|
||||
CMNode masterNode = NodeCenterActions.nodeInfos.get(newMaster);
|
||||
Map<String, String> req = new HashMap<>();
|
||||
req.put("action", "newMasterStart");
|
||||
req.put("members", mems);
|
||||
req.put("onlineMems", onlineMems.toString());
|
||||
req.put("contractID", contractID);
|
||||
req.put("formerMaster", formerMaster);
|
||||
masterNode.connection.controller.sendMsg(JsonUtil.toJson(req));
|
||||
}
|
||||
}
|
||||
}
|
330
src/main/java/org/bdware/server/nodecenter/NCHttpHandler.java
Normal file
330
src/main/java/org/bdware/server/nodecenter/NCHttpHandler.java
Normal file
@ -0,0 +1,330 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.util.ExceptionUtil;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.action.ActionExecutor;
|
||||
import org.bdware.server.action.HttpResultCallback;
|
||||
import org.bdware.server.http.HttpFileHandleAdapter;
|
||||
import org.bdware.server.http.URIHandler;
|
||||
import org.bdware.server.http.URIPath;
|
||||
import org.bdware.server.permission.Role;
|
||||
import org.zz.gmhelper.SM2Util;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
|
||||
|
||||
@Sharable
|
||||
public class NCHttpHandler extends SimpleChannelInboundHandler<HttpObject> {
|
||||
private static final String PARAM_ACTION = "action";
|
||||
private static final String UNSUPPORTED_HTTP_METHOD = "{\"msg\":\"unsupported http method\"}";
|
||||
private static final String UNSUPPORTED_ACTION = "{\"msg\":\"unsupported action\"}";
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCHttpHandler.class);
|
||||
private static final ActionExecutor<ResultCallback, JsonObject> actionExecutor =
|
||||
new ActionExecutor<ResultCallback, JsonObject>(
|
||||
NodeCenterFrameHandler.executorService, new NodeCenterActions(null)) {
|
||||
|
||||
@Override
|
||||
public boolean checkPermission(Action a, JsonObject arg, long per) {
|
||||
boolean flag = a.httpAccess();
|
||||
long val = a.userPermission(); // 使用者必须达到的permission
|
||||
long permission = arg.get("permission").getAsLong();
|
||||
LOGGER.debug("permission" + permission);
|
||||
LOGGER.debug("htttttttttttttp--userpermission:" + val);
|
||||
LOGGER.debug("htttttttttttttp--permission:" + per); // 现有的permission
|
||||
boolean flag2 = false; // 启动http权限后应改为false
|
||||
String status = "refuse";
|
||||
String action = arg.get("action").getAsString();
|
||||
|
||||
if (val == 0) {
|
||||
flag2 = true;
|
||||
} else {
|
||||
flag2 = (permission & val) == val;
|
||||
}
|
||||
|
||||
if (flag && flag2) {
|
||||
status = "accept";
|
||||
}
|
||||
|
||||
String pubkey = "anonymity";
|
||||
if (arg.has("pubKey")) {
|
||||
pubkey = arg.get("pubKey").getAsString();
|
||||
}
|
||||
NodeCenterServer.nodeHttpLogDB.put(
|
||||
action,
|
||||
"{\"action\":\""
|
||||
+ action
|
||||
+ "\",\"pubKey\":\""
|
||||
+ pubkey
|
||||
+ "\",\"date\":"
|
||||
+ System.currentTimeMillis()
|
||||
+ "}");
|
||||
LOGGER.debug("[NCHttpHandler] flag = " + flag + " flag2 = " + flag2);
|
||||
return flag && flag2;
|
||||
}
|
||||
};
|
||||
static TypeToken<Map<String, String>> token = new TypeToken<Map<String, String>>() {};
|
||||
private final HttpFileHandleAdapter fileAdapter;
|
||||
// public static ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
public AtomicInteger counter = new AtomicInteger(0);
|
||||
private URIHandler handler;
|
||||
|
||||
public NCHttpHandler() {
|
||||
FileFilter fileFilter = pathname -> !pathname.getAbsolutePath().contains("..");
|
||||
fileAdapter =
|
||||
new HttpFileHandleAdapter(new File("./WebContent/").getAbsolutePath(), fileFilter) {
|
||||
@URIPath("/")
|
||||
public void loadFile(ChannelHandlerContext ctx, FullHttpRequest req)
|
||||
throws Exception {
|
||||
super.channelRead0(ctx, req);
|
||||
}
|
||||
};
|
||||
handler = new URIHandler();
|
||||
handler.register(this);
|
||||
handler.register(fileAdapter);
|
||||
handler.printURIHandlers();
|
||||
}
|
||||
|
||||
public static ActionExecutor<ResultCallback, JsonObject> getActionExecutor() {
|
||||
return actionExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
@URIPath({"/NodeCenter", "/SCIDE/SCExecutor", "/SCIDE/CMManager", "/SCIDE/SCManager"})
|
||||
public void parseGetAndHandle(ChannelHandlerContext ctx, FullHttpRequest req) {
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(req.uri());
|
||||
Map<String, List<String>> params = decoderQuery.parameters();
|
||||
JsonObject map = new JsonObject();
|
||||
for (String key : params.keySet()) {
|
||||
List<String> val = params.get(key);
|
||||
if (val != null) map.addProperty(key, val.get(0));
|
||||
}
|
||||
String uri = URLDecoder.decode(req.uri()).split("\\?")[1];
|
||||
int index = uri.lastIndexOf('&');
|
||||
String str = uri;
|
||||
if (index != -1) {
|
||||
str = uri.substring(0, index);
|
||||
}
|
||||
injectPermission(map, str);
|
||||
handleReq(map, ctx);
|
||||
}
|
||||
|
||||
@URIPath(
|
||||
method = org.bdware.server.http.HttpMethod.POST,
|
||||
value = {"/NodeCenter", "/SCIDE/SCExecutor", "/SCIDE/CMManager", "/SCIDE/SCManager"})
|
||||
public void parsePostAndHandle(ChannelHandlerContext ctx, FullHttpRequest req)
|
||||
throws UnsupportedEncodingException {
|
||||
ByteBuf content = req.content();
|
||||
JsonObject map =
|
||||
JsonParser.parseReader(new InputStreamReader(new ByteBufInputStream(content)))
|
||||
.getAsJsonObject();
|
||||
// FIXME 感觉不太对劲
|
||||
String uri = URLDecoder.decode(req.uri(), "utf-8").split("\\?")[1];
|
||||
int index = uri.lastIndexOf('&');
|
||||
String str = uri;
|
||||
if (index != -1) {
|
||||
str = uri.substring(0, index);
|
||||
}
|
||||
injectPermission(map, str);
|
||||
handleReq(map, ctx);
|
||||
}
|
||||
|
||||
private JsonObject parseArgInQuery(FullHttpRequest request) {
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(request.uri());
|
||||
Map<String, List<String>> parameters = decoderQuery.parameters();
|
||||
JsonObject transformedParam = new JsonObject();
|
||||
for (String key : parameters.keySet()) {
|
||||
List<String> val = parameters.get(key);
|
||||
if (val != null) transformedParam.addProperty(key, val.get(0));
|
||||
}
|
||||
return transformedParam;
|
||||
}
|
||||
|
||||
@URIPath(
|
||||
method = org.bdware.server.http.HttpMethod.GET,
|
||||
value = {"/doip"})
|
||||
public void handleDOIP(ChannelHandlerContext ctx, FullHttpRequest req) {
|
||||
ByteBuf content = req.content();
|
||||
JsonObject map = parseArgInQuery(req);
|
||||
// FIXME 感觉不太对劲
|
||||
String uri = URLDecoder.decode(req.uri()).split("\\?")[1];
|
||||
int index = uri.lastIndexOf('&');
|
||||
String str = uri;
|
||||
if (index != -1) {
|
||||
str = uri.substring(0, index);
|
||||
}
|
||||
injectPermission(map, str);
|
||||
|
||||
DefaultFullHttpResponse response =
|
||||
new DefaultFullHttpResponse(
|
||||
HttpVersion.HTTP_1_1,
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(MetaIndexAction.search(map).getBytes()));
|
||||
ChannelFuture f = ctx.write(response);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
|
||||
// TODO @fanbo Http查询接口,需支持各类查询,按owner/按关键词/....
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
|
||||
// logger.debug("[NCHttpHandler] TID:" + Thread.currentThread().getId() +
|
||||
// msg.toString());
|
||||
if (msg instanceof FullHttpRequest) {
|
||||
FullHttpRequest request = (FullHttpRequest) msg;
|
||||
handler.handle(ctx, request);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRole(String pubKey) {
|
||||
try {
|
||||
String ret =
|
||||
KeyValueDBUtil.instance.getValue(
|
||||
NCTables.ConfigDB.toString(), "__CenterManager__");
|
||||
if (ret != null && ret.length() > 0) {
|
||||
boolean isCenterManager = (ret.equals(pubKey)); // 表示此节点是否是平台管理员
|
||||
ret = KeyValueDBUtil.instance.getValue(NCTables.NodeUser.toString(), pubKey);
|
||||
String role = "";
|
||||
if (isCenterManager) {
|
||||
role = "CenterManager,";
|
||||
}
|
||||
if (null != ret && !ret.isEmpty()) {
|
||||
role += ret;
|
||||
}
|
||||
if (role.endsWith(",")) {
|
||||
role = role.substring(0, role.length() - 1);
|
||||
} else if (role.isEmpty()) {
|
||||
role = Role.Anonymous.name();
|
||||
}
|
||||
return role;
|
||||
}
|
||||
return Role.Anonymous.name();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Role.Anonymous.name();
|
||||
}
|
||||
}
|
||||
|
||||
private void injectPermission(JsonObject map, String str) {
|
||||
if (map.has("pubKey")) {
|
||||
String pubkey = map.get("pubKey").getAsString();
|
||||
boolean verify = SM2Util.plainStrVerify(pubkey, str, map.get("sign").getAsString());
|
||||
LOGGER.debug("[CMHttpHandler] HTTP POST 请求验签为 " + verify);
|
||||
|
||||
if (verify) {
|
||||
// 查permission
|
||||
String ret = getRole(pubkey);
|
||||
long permission;
|
||||
if (ret != null && ret.length() > 0) {
|
||||
permission = 0x86000d41L | Role.compoundValue(ret.split(","));
|
||||
} else {
|
||||
permission = Role.compoundValue(ret.split(","));
|
||||
}
|
||||
map.addProperty("permission", permission + "");
|
||||
LOGGER.debug("[CMHttpHandler] http 请求查看用户权限为 : " + permission);
|
||||
} else {
|
||||
map.addProperty("permission", 0 + "");
|
||||
}
|
||||
} else {
|
||||
map.addProperty("permission", 0 + "");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleReq(final JsonObject map, final ChannelHandlerContext ctx) {
|
||||
try {
|
||||
map.addProperty("fromHttp", "true");
|
||||
String ret = null;
|
||||
String action = null;
|
||||
if (!map.has("action")) {
|
||||
ret = UNSUPPORTED_ACTION;
|
||||
} else {
|
||||
action = map.get("action").getAsString();
|
||||
}
|
||||
if (action != null) {
|
||||
HttpResultCallback cb;
|
||||
|
||||
if (action.equals("takeScreenshot")) {
|
||||
cb = new HttpResultCallback(ctx, map.get("callback").getAsString());
|
||||
cb.setDecodeBase64();
|
||||
cb.addHeader("Content-type", "image/png");
|
||||
|
||||
} else if (action.equals("executeContract")) {
|
||||
cb = new HttpResultCallback(ctx, map.get("callback").getAsString());
|
||||
cb.addHeader("charset", "utf-8");
|
||||
cb.addHeader("Content-type", "text/plain");
|
||||
|
||||
} else {
|
||||
|
||||
if (map.has("callback"))
|
||||
cb = new HttpResultCallback(ctx, map.get("callback").getAsString());
|
||||
else cb = new HttpResultCallback(ctx, null);
|
||||
|
||||
cb.addHeader("charset", "utf-8");
|
||||
cb.addHeader("Content-type", "application/json");
|
||||
}
|
||||
actionExecutor.handle(action, map, cb);
|
||||
} else {
|
||||
DefaultFullHttpResponse response =
|
||||
new DefaultFullHttpResponse(
|
||||
HttpVersion.HTTP_1_1, OK, Unpooled.wrappedBuffer(ret.getBytes()));
|
||||
ChannelFuture f = ctx.write(response);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
DefaultFullHttpResponse response =
|
||||
new DefaultFullHttpResponse(
|
||||
HttpVersion.HTTP_1_1,
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(e.getMessage().getBytes()));
|
||||
ChannelFuture f = ctx.write(response);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
|
||||
} catch (Exception e) {
|
||||
Map<String, String> ret = new HashMap<>();
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
ret.put("msg", bo.toString());
|
||||
DefaultFullHttpResponse response =
|
||||
new DefaultFullHttpResponse(
|
||||
HttpVersion.HTTP_1_1,
|
||||
OK,
|
||||
Unpooled.wrappedBuffer(JsonUtil.toJson(ret).getBytes()));
|
||||
ChannelFuture f = ctx.write(response);
|
||||
f.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
LOGGER.warn("catch exception in " + this + ": " + cause.getClass().getSimpleName());
|
||||
LOGGER.debug(ExceptionUtil.exceptionToString(cause));
|
||||
ctx.close();
|
||||
}
|
||||
}
|
473
src/main/java/org/bdware/server/nodecenter/NCManagerAction.java
Normal file
473
src/main/java/org/bdware/server/nodecenter/NCManagerAction.java
Normal file
@ -0,0 +1,473 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.Jedion.KV;
|
||||
import org.bdware.sc.conn.ByteUtil;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.encrypt.HardwareInfo;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.permission.Role;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
import org.zz.gmhelper.BCECUtil;
|
||||
import org.zz.gmhelper.SM2Util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
// CenterPortal用户管理相关
|
||||
public class NCManagerAction {
|
||||
// key为centerManager的数据表示平台管理员(中心管理员)
|
||||
public static final String centerManger = "__CenterManager__";
|
||||
static final String Licence = "__LICENCE___";
|
||||
static final ECPublicKeyParameters licencePub =
|
||||
BCECUtil.createECPublicKeyFromStrParameters(
|
||||
"04844412ecb77b07d5ad7097c488ae9dff1013b310d2311f8bd84c491642011e1a6a7041bae8c2ad75da29c27e320bd430abc723cf6bcb0490afc82cc26e6d5637",
|
||||
SM2Util.CURVE,
|
||||
SM2Util.DOMAIN_PARAMS);
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCManagerAction.class);
|
||||
String sessionID = null;
|
||||
String pubKey;
|
||||
Random random = new Random();
|
||||
private NodeCenterWSFrameHandler handler;
|
||||
|
||||
public NCManagerAction(NodeCenterWSFrameHandler nodeCenterWSFrameHandler) {
|
||||
this.handler = nodeCenterWSFrameHandler;
|
||||
pubKey = null;
|
||||
}
|
||||
|
||||
public static boolean isCenterManager(String pubkey) {
|
||||
String ret = KeyValueDBUtil.instance.getValue(NCTables.ConfigDB.toString(), centerManger);
|
||||
LOGGER.debug("centerManger: " + ret);
|
||||
return !StringUtil.isNullOrEmpty(ret)
|
||||
&& !StringUtil.isNullOrEmpty(pubkey)
|
||||
&& pubkey.equals(ret);
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void getNodeSessionID(JsonObject json, ResultCallback resultCallback) {
|
||||
getSessionID(json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void getSessionID(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
sessionID = random.nextLong() + "_session";
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onSessionID");
|
||||
result.put("session", sessionID);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("time:" + (end - start) + "data:" + JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void getNodeRole(JsonObject json, ResultCallback resultCallback) {
|
||||
getRole(json, resultCallback);
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void getManagerPubkey(JsonObject json, ResultCallback resultCallback) {
|
||||
String ret = KeyValueDBUtil.instance.getValue(NCTables.ConfigDB.toString(), centerManger);
|
||||
resultCallback.onResult("{\"action\":\"onGetManagerPubkey\",\"data\":\"" + ret + "\"}");
|
||||
}
|
||||
|
||||
public void getRole(JsonObject json, ResultCallback resultCallback) {
|
||||
if (pubKey == null) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onLogin\",\"data\":\"" + Role.Anonymous.name() + "\"}");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String ret =
|
||||
KeyValueDBUtil.instance.getValue(NCTables.ConfigDB.toString(), centerManger);
|
||||
if (ret != null && ret.length() > 0) {
|
||||
boolean isCenterManager = (ret.equals(pubKey)); // 表示此节点是否是平台管理员
|
||||
ret = KeyValueDBUtil.instance.getValue(NCTables.NodeUser.toString(), pubKey);
|
||||
String role = "";
|
||||
if (isCenterManager) {
|
||||
role = "CenterManager,";
|
||||
}
|
||||
if (null != ret && !ret.isEmpty()) {
|
||||
role += ret;
|
||||
}
|
||||
if (role.endsWith(",")) {
|
||||
role = role.substring(0, role.length() - 1);
|
||||
} else if (role.isEmpty()) {
|
||||
role = Role.Anonymous.name();
|
||||
}
|
||||
handler.setPermission(Role.compoundValue(role.split(",")));
|
||||
resultCallback.onResult("{\"action\":\"onLogin\",\"data\":\"" + role + "\"}");
|
||||
} else {
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ConfigDB.toString(), centerManger, pubKey);
|
||||
handler.setPermission(0x30000ffL);
|
||||
resultCallback.onResult("{\"action\":\"onLogin\",\"data\":\"CenterManager\"}");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onLogin\",\"data\":\"" + Role.Anonymous.name() + "\"}");
|
||||
}
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void login(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
if (sessionID == null) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onLogin\",\"data\":\"" + Role.Anonymous.name() + "\"}");
|
||||
return;
|
||||
}
|
||||
String signature = json.get("signature").getAsString();
|
||||
String pubKey = json.get("pubKey").getAsString();
|
||||
|
||||
boolean result = SM2Util.plainStrVerify(pubKey, sessionID, signature);
|
||||
LOGGER.debug("session:" + (sessionID));
|
||||
if (result) {
|
||||
this.pubKey = pubKey;
|
||||
LOGGER.debug("设置公钥" + pubKey);
|
||||
getRole(json, resultCallback);
|
||||
} else {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onLogin\",\"data\":\"" + Role.Anonymous.name() + "\"}");
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("time:" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 0)
|
||||
public void applyRole(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
if (pubKey == null) {
|
||||
resultCallback.onResult("{\"action\":\"onApplyRole\",\"data\":\"missing pubKey\"}");
|
||||
return;
|
||||
}
|
||||
if (json.has("role")) {
|
||||
Role role = Role.parse(json.get("role").getAsString());
|
||||
if (role != Role.Anonymous) {
|
||||
applyAtDB(role, resultCallback, start);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resultCallback.onResult("{\"action\":\"onApplyRole\",\"data\":\"failed\"}");
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 6)
|
||||
public void addNode(JsonObject json, ResultCallback resultCallback) {
|
||||
try {
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.NodeUser.toString(),
|
||||
json.get("nodePubKey").getAsString(),
|
||||
Role.Node.toString());
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.NodeTime.toString(),
|
||||
json.get("nodePubKey").getAsString(),
|
||||
Long.toString(new Date().getTime()));
|
||||
resultCallback.onResult("{\"action\":\"onAddNodes\",\"data\":\"success\"}");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultCallback.onResult("{\"action\":\"onAddNodes\",\"data\":\"failed\"}");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyAtDB(Role role, ResultCallback resultCallback, long start) {
|
||||
String str = KeyValueDBUtil.instance.getValue(NCTables.ApplyRole.toString(), pubKey);
|
||||
String already = KeyValueDBUtil.instance.getValue(NCTables.NodeUser.toString(), pubKey);
|
||||
if (already != null && already.contains(role.toString())) {
|
||||
resultCallback.onResult("{\"action\":\"onApplyRole\",\"data\":\"already has!\"}");
|
||||
return;
|
||||
}
|
||||
if (str == null || str.length() == 0) {
|
||||
KeyValueDBUtil.instance.setValue(NCTables.ApplyRole.toString(), pubKey, role.name());
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ApplyTime.toString(), pubKey, Long.toString(new Date().getTime()));
|
||||
} else {
|
||||
if (!str.contains(role.name())) {
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ApplyRole.toString(), pubKey, str + "," + role.name());
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ApplyTime.toString(), pubKey, Long.toString(new Date().getTime()));
|
||||
}
|
||||
}
|
||||
resultCallback.onResult("{\"action\":\"onApplyRole\",\"data\":\"success\"}");
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 3)
|
||||
public void listAllUsers(JsonObject json, ResultCallback resultCallback) {
|
||||
List<KV> kv = KeyValueDBUtil.instance.getKeyValues(NCTables.NodeUser.toString());
|
||||
List<KV> time = KeyValueDBUtil.instance.getKeyValues(NCTables.NodeTime.toString());
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ResultBack result = new ResultBack();
|
||||
ret.put("kv", kv);
|
||||
ret.put("time", time);
|
||||
result.action = "onListAllUsers";
|
||||
result.data = ret;
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 2)
|
||||
public void authNodeManager(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
String pubKey = json.get("pubKey").getAsString();
|
||||
boolean isAccept = json.get("isAccept").getAsBoolean();
|
||||
LOGGER.debug("[NCManagerAction] " + json.toString());
|
||||
if (pubKey == null || pubKey.length() == 0) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onAuthNodeManager\",\"data\":\"missing pubKey\"}");
|
||||
return;
|
||||
}
|
||||
if (!isAccept) {
|
||||
KeyValueDBUtil.instance.delete(NCTables.ApplyRole.toString(), pubKey);
|
||||
KeyValueDBUtil.instance.delete(NCTables.ApplyTime.toString(), pubKey);
|
||||
resultCallback.onResult("{\"action\":\"onAuthNodeManager\",\"data\":\"success\"}");
|
||||
return;
|
||||
}
|
||||
String already = KeyValueDBUtil.instance.getValue(NCTables.NodeUser.toString(), pubKey);
|
||||
String roles = KeyValueDBUtil.instance.getValue(NCTables.ApplyRole.toString(), pubKey);
|
||||
if (roles == null || roles.length() == 0) {
|
||||
resultCallback.onResult("{\"action\":\"onAuthNodeManager\",\"data\":\"empty apply\"}");
|
||||
return;
|
||||
}
|
||||
if (already != null && already.length() > 0) {
|
||||
already += "," + roles;
|
||||
} else {
|
||||
already = roles;
|
||||
}
|
||||
|
||||
KeyValueDBUtil.instance.setValue(NCTables.NodeUser.toString(), pubKey, already);
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.NodeTime.toString(), pubKey, Long.toString(new Date().getTime()));
|
||||
KeyValueDBUtil.instance.delete(NCTables.ApplyRole.toString(), pubKey);
|
||||
KeyValueDBUtil.instance.delete(NCTables.ApplyTime.toString(), pubKey);
|
||||
resultCallback.onResult("{\"action\":\"onAuthNodeManager\",\"data\":\"success\"}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[authNodeManager:time]" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 4)
|
||||
public void listApplyList(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
List<KV> kv = KeyValueDBUtil.instance.getKeyValues(NCTables.ApplyRole.toString());
|
||||
List<KV> time = KeyValueDBUtil.instance.getKeyValues(NCTables.ApplyTime.toString());
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("kv", kv);
|
||||
ret.put("time", time);
|
||||
ResultBack result = new ResultBack();
|
||||
result.action = "onListApplyList";
|
||||
result.data = ret;
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listApplyList:time]" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 5)
|
||||
public void delete(JsonObject json, ResultCallback resultCallback) {
|
||||
String pubKey = json.get("pubKey").getAsString();
|
||||
KeyValueDBUtil.instance.delete(NCTables.NodeUser.toString(), pubKey);
|
||||
KeyValueDBUtil.instance.delete(NCTables.NodeTime.toString(), pubKey);
|
||||
resultCallback.onResult("{\"action\":\"onDelete\",\"data\":\"success\"}");
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 4)
|
||||
public void listLicence(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
String licence = KeyValueDBUtil.instance.getValue(NCTables.ConfigDB.toString(), Licence);
|
||||
if (licence == null || licence.length() == 0) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":" + 0 + ",\"dueDate\":\"已过期\"}");
|
||||
return;
|
||||
}
|
||||
json = JsonParser.parseString(licence).getAsJsonObject();
|
||||
String sign = json.get("sign").getAsString();
|
||||
String content = json.get("content").getAsString();
|
||||
if (StringUtil.isNullOrEmpty(sign) || StringUtil.isNullOrEmpty(content)) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":0,\"dueDate\":\"已过期\"}");
|
||||
return;
|
||||
}
|
||||
long expiredDate;
|
||||
long nodeCount;
|
||||
try {
|
||||
JsonObject jo = JsonParser.parseString(content).getAsJsonObject();
|
||||
nodeCount = jo.get("nodeCount").getAsLong();
|
||||
expiredDate = jo.get("expiredDate").getAsLong();
|
||||
} catch (Exception e) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":0,\"dueDate\":\"已过期\"}");
|
||||
return;
|
||||
}
|
||||
if (expiredDate == 0 || nodeCount == 0) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":0,\"dueDate\":\"已过期\"}");
|
||||
return;
|
||||
}
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
boolean verify =
|
||||
SM2Util.verify(licencePub, content.getBytes(), ByteUtils.fromHexString(sign));
|
||||
if (verify) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":"
|
||||
+ nodeCount
|
||||
+ ",\"dueDate\":\""
|
||||
+ format.format(new Date(expiredDate))
|
||||
+ "\"}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listLicence:time]" + (end - start));
|
||||
} else {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onListLicence\",\"nodeCount\":0,\"dueDate\":\"已过期\"}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listLicence:time]" + (end - start));
|
||||
}
|
||||
}
|
||||
|
||||
@Action(userPermission = 1L << 2L)
|
||||
public void updateLicence(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
String sign = json.get("sign").getAsString();
|
||||
String content = json.get("content").getAsString();
|
||||
if (StringUtil.isNullOrEmpty(sign) || StringUtil.isNullOrEmpty(content)) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onUpdateLicence\",\"data\":\"missing signature or content\"}");
|
||||
return;
|
||||
}
|
||||
long expiredDate;
|
||||
long nodeCount;
|
||||
String uuid;
|
||||
try {
|
||||
JsonObject jo = JsonParser.parseString(content).getAsJsonObject();
|
||||
nodeCount = jo.get("nodeCount").getAsLong();
|
||||
expiredDate = jo.get("expiredDate").getAsLong();
|
||||
uuid = jo.get("uuid").getAsString();
|
||||
|
||||
} catch (Exception e) {
|
||||
resultCallback.onResult("{\"action\":\"onUpdateLicence\",\"data\":\"content error\"}");
|
||||
return;
|
||||
}
|
||||
if (expiredDate == 0 || nodeCount == 0) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onUpdateLicence\",\"data\":\"parse expiredDate/nodeCount error\"}");
|
||||
return;
|
||||
}
|
||||
if (!uuid.equals(
|
||||
ByteUtil.encodeBASE64(HardwareInfo.getCPUID().getBytes()).replaceAll("\n", ""))) {
|
||||
resultCallback.onResult(
|
||||
"{\"action\":\"onUpdateLicence\",\"data\":\"invalid licence\"}");
|
||||
return;
|
||||
}
|
||||
boolean verify =
|
||||
SM2Util.verify(licencePub, content.getBytes(), ByteUtils.fromHexString(sign));
|
||||
|
||||
if (verify) {
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.ConfigDB.toString(), Licence, json.toString());
|
||||
resultCallback.onResult("{\"action\":\"onUpdateLicence\",\"data\":\"success\"}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listLicence:time]" + (end - start));
|
||||
return;
|
||||
} else resultCallback.onResult("{\"action\":\"onUpdateLicence\",\"data\":\"failed\"}");
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[updateLicence:time]" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 9)
|
||||
public void getOtherNC(JsonObject json, ResultCallback resultCallback) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onGetOtherNC");
|
||||
String s = OtherNCProxy.instance.getOtherNCs().replace(";", " ");
|
||||
result.put("address", s);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
// 改为NodeManager权限
|
||||
@Action(userPermission = 1 << 9)
|
||||
public void changeOtherNC(JsonObject json, ResultCallback resultCallback) {
|
||||
String add = json.get("data").getAsString().replace(" ", ";");
|
||||
String s = OtherNCProxy.instance.setOtherNCs(add).replace(";", " ");
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onGetOtherNC");
|
||||
result.put("address", s);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
// NodeManager权限
|
||||
@Action(userPermission = 1 << 9)
|
||||
public void changeNCFile(JsonObject json, ResultCallback resultCallback) {
|
||||
String add = json.get("data").getAsString();
|
||||
String s = OtherNCProxy.instance.setNCFile(add);
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onGetNCFile");
|
||||
result.put("fileName", s);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 9)
|
||||
public void getNCFile(JsonObject json, ResultCallback resultCallback) {
|
||||
String s = OtherNCProxy.instance.getNCFile();
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onGetNCFile");
|
||||
result.put("fileName", s);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
|
||||
// TODO 迁移合约实例(从节点A将合约M的实例迁移到节点B)的权限?
|
||||
/*
|
||||
* now only support Sole contract type
|
||||
*/
|
||||
@Action(userPermission = 0)
|
||||
public void transferContractInstance(JsonObject json, ResultCallback resultCallback) {
|
||||
LOGGER.info("transferContractInstance");
|
||||
|
||||
String node1ID = json.get("node1ID").getAsString();
|
||||
String node2ID = json.get("node2ID").getAsString();
|
||||
String contractID = json.get("contractID").getAsString();
|
||||
|
||||
CMNode node1 = NodeCenterActions.nodeInfos.get(node1ID);
|
||||
if (node1 == null) {
|
||||
LOGGER.info("node1 " + node1ID + " is null!");
|
||||
return;
|
||||
}
|
||||
if (node2ID == null) {
|
||||
LOGGER.info("node2 " + node1ID + " is null!");
|
||||
return;
|
||||
}
|
||||
if (node1ID.equals(node2ID)) {
|
||||
LOGGER.info("node1 and node2 is the same node.");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put("action", "transferInstance");
|
||||
request.put("contractID", contractID);
|
||||
request.put("nodeID", node2ID);
|
||||
CMNode node2 = NodeCenterActions.nodeInfos.get(node2ID);
|
||||
if (node2 == null) {
|
||||
LOGGER.info("node " + node2ID + " is null!");
|
||||
return;
|
||||
}
|
||||
request.put("address", node2.masterAddress);
|
||||
node1.connection.controller.sendMsg(JsonUtil.toJson(request));
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("action", "onTransfer");
|
||||
result.put(
|
||||
"data",
|
||||
"now start transfer contract "
|
||||
+ contractID
|
||||
+ " from node:"
|
||||
+ node1ID
|
||||
+ " to node:"
|
||||
+ node2ID);
|
||||
resultCallback.onResult(JsonUtil.toJson(result));
|
||||
}
|
||||
}
|
21
src/main/java/org/bdware/server/nodecenter/NCTables.java
Normal file
21
src/main/java/org/bdware/server/nodecenter/NCTables.java
Normal file
@ -0,0 +1,21 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
public enum NCTables {
|
||||
NodeUser,
|
||||
NodeTime,
|
||||
ApplyRole,
|
||||
ApplyTime,
|
||||
NodeHttpLog,
|
||||
ContractMeta,
|
||||
ConfigDB,
|
||||
NodeTcpLog,
|
||||
NodesDB,
|
||||
TrustUnitsDB,
|
||||
OtherNCs,
|
||||
NCFile,
|
||||
ApplyNodeManager;
|
||||
|
||||
public String toString() {
|
||||
return "NC_" + super.toString();
|
||||
}
|
||||
}
|
122
src/main/java/org/bdware/server/nodecenter/NCUDPRunner.java
Normal file
122
src/main/java/org/bdware/server/nodecenter/NCUDPRunner.java
Normal file
@ -0,0 +1,122 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.udp.UDPMessage;
|
||||
import org.bdware.sc.udp.UDPNode;
|
||||
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.Action;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class NCUDPRunner extends Thread {
|
||||
private static final Logger LOGGER = LogManager.getLogger(NCUDPRunner.class);
|
||||
public static int mainPort;
|
||||
public ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
public int port;
|
||||
boolean ready = false;
|
||||
Map<Integer, org.bdware.sc.udp.UDPNode> id2IP;
|
||||
private DatagramSocket socket;
|
||||
|
||||
public NCUDPRunner(Map<Integer, UDPNode> id2ip2) {
|
||||
// TODO Auto-generated constructor stub
|
||||
this.id2IP = id2ip2;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// TimerTask task = new TimerTask() {
|
||||
//
|
||||
// @Override
|
||||
// public void run(Timeout arg0) throws Exception {
|
||||
// Set<Integer> nodes = new HashSet<Integer>();
|
||||
// for (Integer i:id2IP.keySet()) {
|
||||
// UDPNode node = id2IP.get(i);
|
||||
// if (System.currentTimeMillis()-node.lastUpdatedTime<60*1000) {
|
||||
// nodes.remove(i);
|
||||
// }
|
||||
// }
|
||||
// for (Integer i:nodes)
|
||||
// node.re
|
||||
// }
|
||||
// };
|
||||
id2IP = new HashMap<Integer, UDPNode>();
|
||||
int startPort = mainPort;
|
||||
while (true) {
|
||||
try {
|
||||
socket = new DatagramSocket(startPort);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
startPort++;
|
||||
}
|
||||
}
|
||||
this.port = startPort;
|
||||
ready = true;
|
||||
while (true) {
|
||||
try {
|
||||
final DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
|
||||
socket.receive(request);
|
||||
final UDPMessage msg = UDPMessage.parse(request.getData(), request.getLength());
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
onUDPMessage(msg, request);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Excpetion in:" + port);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onUDPMessage(UDPMessage msg, DatagramPacket request) {
|
||||
switch (msg.type) {
|
||||
case shakeHand:
|
||||
LOGGER.debug(
|
||||
"[NCUDPRunner] shakeHand:"
|
||||
+ request.getAddress().getHostAddress()
|
||||
+ ":"
|
||||
+ request.getPort());
|
||||
id2IP.put(msg.id, new UDPNode(request.getSocketAddress()));
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@Action
|
||||
public void listUDPNodes(JsonObject json, ResultCallback rc) {
|
||||
Map<String, String> ret = new HashMap<String, String>();
|
||||
ret.put("action", "onListUDPNodes");
|
||||
for (Integer i : id2IP.keySet()) {
|
||||
UDPNode node = id2IP.get(i);
|
||||
InetSocketAddress address = (InetSocketAddress) (node.addr);
|
||||
ret.put("id_" + i, address.getHostString() + ":" + address.getPort());
|
||||
}
|
||||
ret.put("udpPort", port + "");
|
||||
|
||||
rc.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
public String getUDPAddr(Integer udpid) {
|
||||
LOGGER.debug(udpid);
|
||||
UDPNode node = id2IP.get(udpid);
|
||||
if (node != null) {
|
||||
InetSocketAddress address = (InetSocketAddress) (node.addr);
|
||||
return address.getHostString() + ":" + address.getPort();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove(String udpID) {
|
||||
id2IP.remove(Integer.valueOf(udpID));
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
public class NameAndID {
|
||||
String name,id;
|
||||
}
|
1783
src/main/java/org/bdware/server/nodecenter/NodeCenterActions.java
Normal file
1783
src/main/java/org/bdware/server/nodecenter/NodeCenterActions.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,168 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.action.ActionExecutor;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class NodeCenterFrameHandler extends SimpleChannelInboundHandler<Object> {
|
||||
private static final Logger LOGGER = LogManager.getLogger(LogActions.class);
|
||||
static ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
public String pubKey;
|
||||
NodeCenterActions actions;
|
||||
MasterActions masterActions;
|
||||
ActionExecutor<ResultCallback, JsonObject> ae;
|
||||
ChannelHandlerContext ctx;
|
||||
|
||||
public NodeCenterFrameHandler() {
|
||||
actions = new NodeCenterActions(this);
|
||||
MetaIndexAction.controller = this;
|
||||
// TODO 添加那个UnitAction.
|
||||
ae =
|
||||
new ActionExecutor<ResultCallback, JsonObject>(
|
||||
executorService, actions, new MetaIndexAction()) {
|
||||
@Override
|
||||
public boolean checkPermission(
|
||||
Action a, final JsonObject args, long permission) {
|
||||
long val = a.userPermission();
|
||||
boolean flag;
|
||||
String status = "refuse";
|
||||
String action = args.get("action").getAsString();
|
||||
if (val == 0) {
|
||||
flag = true;
|
||||
status = "accept";
|
||||
} else if ((permission & val) == val) {
|
||||
flag = true;
|
||||
status = "accept";
|
||||
} else {
|
||||
flag = false;
|
||||
}
|
||||
if (!action.contains("checkAlive"))
|
||||
NodeCenterServer.nodeTcpLogDB.put(
|
||||
action,
|
||||
"{\"action\":\""
|
||||
+ action
|
||||
+ "\",\"pubKey\":\""
|
||||
+ pubKey
|
||||
+ "\",\"status\":\""
|
||||
+ status
|
||||
+ "\",\"date\":"
|
||||
+ System.currentTimeMillis()
|
||||
+ "}");
|
||||
return flag;
|
||||
}
|
||||
};
|
||||
LOGGER.info("create NodeCenterFrameHandler instance succeed!");
|
||||
}
|
||||
|
||||
public void setPermission(long l) {
|
||||
ae.permission = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Object frame) {
|
||||
this.ctx = ctx;
|
||||
JsonObject map;
|
||||
try {
|
||||
map =
|
||||
JsonParser.parseReader(
|
||||
new InputStreamReader(new ByteBufInputStream((ByteBuf) frame)))
|
||||
.getAsJsonObject();
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("can't handle msg! " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
Response response;
|
||||
try {
|
||||
final String action = map.get("action").getAsString();
|
||||
// System.out.println("[NodeCenterFramHandler] handle:" + action);
|
||||
ae.handle(
|
||||
action,
|
||||
map,
|
||||
new ResultCallback() {
|
||||
@Override
|
||||
public void onResult(String ret) {
|
||||
sendMsg(ret);
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException e) {
|
||||
response = new Response();
|
||||
response.action = "onException";
|
||||
response.data = e.getMessage();
|
||||
LOGGER.error(JsonUtil.toJson(response));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
response = new Response();
|
||||
response.action = "onException";
|
||||
String[] strs = bo.toString().split("\n");
|
||||
StringBuilder ret = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String s : strs) {
|
||||
if (s.contains("sun.reflect")
|
||||
|| s.contains("java.lang.reflect")
|
||||
|| s.contains("org.apache")
|
||||
|| s.contains("java.util")
|
||||
|| s.contains("java.lang")
|
||||
|| s.contains("io.netty")) {
|
||||
continue;
|
||||
}
|
||||
ret.append(s);
|
||||
ret.append("\n");
|
||||
if (count++ > 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
response.data = ret.toString();
|
||||
LOGGER.error(JsonUtil.toJson(response));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMsg(String json) {
|
||||
if (ctx != null) {
|
||||
// System.out.println("[NodeCenterFrame send] TID:" + Thread.currentThread().getId() + "
|
||||
// isOpen:"
|
||||
// + ctx.channel().isOpen() + " isActive:" + ctx.channel().isActive() + " -->" + json);
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(json.getBytes());
|
||||
ctx.channel().writeAndFlush(buf);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendEMsg(String msg) {
|
||||
Response r = new Response();
|
||||
r.action = "receiveEMsg";
|
||||
r.data = msg;
|
||||
sendMsg(JsonUtil.toJson(r));
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return ctx.channel().isOpen();
|
||||
}
|
||||
|
||||
static class Response {
|
||||
public String cid;
|
||||
public String analysisResult;
|
||||
String responseID;
|
||||
String action;
|
||||
Object data;
|
||||
long executeTime;
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.action.ActionExecutor;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class NodeCenterWSFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
|
||||
public static ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
private static final Logger LOGGER = LogManager.getLogger(NodeCenterWSFrameHandler.class);
|
||||
StringBuilder dataCache = new StringBuilder();
|
||||
ActionExecutor<ResultCallback, JsonObject> ae;
|
||||
private ChannelHandlerContext ctx;
|
||||
private NCManagerAction managerAction;
|
||||
private LogActions logActions;
|
||||
private UnitActions unitActions;
|
||||
|
||||
public NodeCenterWSFrameHandler() {
|
||||
managerAction = new NCManagerAction(this);
|
||||
logActions = new LogActions(managerAction);
|
||||
unitActions = new UnitActions(managerAction);
|
||||
|
||||
|
||||
ae =
|
||||
new ActionExecutor<ResultCallback, JsonObject>(
|
||||
executorService, managerAction, logActions, unitActions, new MetaIndexAction(), new TracingAction()) {
|
||||
@Override
|
||||
public boolean checkPermission(Action a, JsonObject arg, long permission) {
|
||||
// Permission userPermission = a.userPermission();
|
||||
// long val=userPermission.getValue();
|
||||
long val = a.userPermission();
|
||||
String pubKey = managerAction.pubKey;
|
||||
String action = arg.get("action").getAsString();
|
||||
LOGGER.debug("permission" + permission);
|
||||
LOGGER.debug("userPermission" + val);
|
||||
NodeCenterServer.nodeHttpLogDB.put(
|
||||
action,
|
||||
"{\"action\":\""
|
||||
+ action
|
||||
+ "\",\"pubKey\":\""
|
||||
+ pubKey
|
||||
+ "\",\"date\":"
|
||||
+ System.currentTimeMillis()
|
||||
+ "}");
|
||||
|
||||
// if (val == 0) return true;
|
||||
// return true;
|
||||
if ((permission & val) == val) {
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ActionExecutor getAE() {
|
||||
return ae;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(final ChannelHandlerContext ctx, WebSocketFrame frame)
|
||||
throws Exception {
|
||||
// ping and pong frames already handled
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
// Send the uppercase string back.
|
||||
this.ctx = ctx;
|
||||
String request = ((TextWebSocketFrame) frame).text();
|
||||
LOGGER.debug("[Websocket receive]" + request);
|
||||
JsonObject map = null;
|
||||
try {
|
||||
map = new JsonParser().parse(request).getAsJsonObject();
|
||||
} catch (Exception e) {
|
||||
Response response = new Response();
|
||||
response.action = "onException";
|
||||
response.data = "msg is not JSON format";
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.toJson(response)));
|
||||
return;
|
||||
}
|
||||
Response response = new Response();
|
||||
response.action = "sendNextSegment";
|
||||
try {
|
||||
boolean isSegment = false;
|
||||
if (map.has("isSegment")) isSegment = map.get("isSegment").getAsBoolean();
|
||||
if (isSegment) {
|
||||
dataCache.append(map.get("data").getAsString());
|
||||
response = new Response();
|
||||
response.action = "sendNextSegment";
|
||||
ctx.channel()
|
||||
.writeAndFlush(new TextWebSocketFrame(JsonUtil.toJson(response)));
|
||||
return;
|
||||
} else {
|
||||
if (dataCache.length() > 0) {
|
||||
dataCache.append(map.get("data").getAsString());
|
||||
String dataStr = dataCache.toString();
|
||||
LOGGER.debug("[WebSocketFrame] DataString:" + dataStr);
|
||||
map = new JsonParser().parse(dataStr).getAsJsonObject();
|
||||
dataCache = new StringBuilder();
|
||||
}
|
||||
}
|
||||
String action = map.get("action").getAsString();
|
||||
ae.handle(
|
||||
action,
|
||||
map,
|
||||
new ResultCallback() {
|
||||
@Override
|
||||
public void onResult(String ret) {
|
||||
if (ret != null)
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame(ret));
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException e) {
|
||||
response = new Response();
|
||||
response.action = "onException";
|
||||
response.data = e.getMessage();
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame((JsonUtil.toJson(response))));
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
response = new Response();
|
||||
response.action = "onException";
|
||||
String[] strs = bo.toString().split("\n");
|
||||
String ret = "";
|
||||
int count = 0;
|
||||
for (String s : strs) {
|
||||
if (s.contains("sun.reflect")) continue;
|
||||
if (s.contains("java.lang.reflect")) continue;
|
||||
if (s.contains("org.apache")) continue;
|
||||
if (s.contains("java.util")) continue;
|
||||
if (s.contains("java.lang")) continue;
|
||||
if (s.contains("io.netty")) continue;
|
||||
ret += s;
|
||||
ret += "\n";
|
||||
if (count++ > 5) break;
|
||||
}
|
||||
response.data = ret;
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.toJson(response)));
|
||||
}
|
||||
|
||||
} else {
|
||||
Response response = new Response();
|
||||
response.action = "onException";
|
||||
response.data = "unsupported frame";
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame((JsonUtil.toJson(response))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMsg(String json) {
|
||||
LOGGER.debug("[WebSocketFrameHandler] sendMsg:" + json);
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame(json));
|
||||
}
|
||||
|
||||
public void setPermission(long i) {
|
||||
ae.permission = i;
|
||||
}
|
||||
}
|
287
src/main/java/org/bdware/server/nodecenter/OtherNCProxy.java
Normal file
287
src/main/java/org/bdware/server/nodecenter/OtherNCProxy.java
Normal file
@ -0,0 +1,287 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.bean.ContractExecType;
|
||||
import org.bdware.sc.bean.OtherNCInfo;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.NodeCenterServer;
|
||||
import org.bdware.server.ws.DelimiterCodec;
|
||||
import org.zz.gmhelper.SM2KeyPair;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class OtherNCProxy {
|
||||
private static final Logger LOGGER = LogManager.getLogger(OtherNCProxy.class);
|
||||
public static OtherNCProxy instance = new OtherNCProxy();
|
||||
private final TreeMap<String, List<OtherNCInfo>> otherNodeCenterInfos = new TreeMap<>(); //key为NC节点的pubkey(非一致的)
|
||||
public Map<String, NCConnector> connList = new ConcurrentHashMap<>(); //连接别的NC key为ip:port
|
||||
public Set<String> ncAdds = ConcurrentHashMap.newKeySet(); //其他NC的ip:port
|
||||
public SM2KeyPair sm2; //NC证书
|
||||
|
||||
private OtherNCProxy() {
|
||||
}
|
||||
|
||||
// 从DB中加载OtherNC和NCFile的信息
|
||||
public void init() {
|
||||
LOGGER.debug("[OtherNCProxy] init : ");
|
||||
|
||||
loadOtherNCs();
|
||||
LOGGER.debug("load other ncs");
|
||||
|
||||
loadNCFile();
|
||||
LOGGER.debug("load nc file");
|
||||
|
||||
periodUpdate();
|
||||
LOGGER.debug("period update");
|
||||
|
||||
LOGGER.info("OtherNCProxy init done!");
|
||||
}
|
||||
|
||||
public void periodUpdate() {
|
||||
NodeCenterServer.scheduledThreadPool.scheduleWithFixedDelay(
|
||||
() -> {
|
||||
},
|
||||
0,
|
||||
30,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void loadOtherNCs() {
|
||||
LOGGER.debug("loadOtherNCs : ");
|
||||
|
||||
String res = getOtherNCs();
|
||||
if (res != null && !res.equals("")) {
|
||||
String[] strArr = res.split(";");
|
||||
ncAdds.clear();
|
||||
ncAdds.addAll(Arrays.asList(strArr));
|
||||
|
||||
LOGGER.debug("now ncAdds contains: ");
|
||||
for (String s : strArr) {
|
||||
LOGGER.debug(s);
|
||||
}
|
||||
|
||||
if (ncAdds.isEmpty()) {
|
||||
KeyValueDBUtil.instance.setValue(NCTables.OtherNCs.toString(), "address", "");
|
||||
}
|
||||
} else {
|
||||
ncAdds.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 配置一致的NC证书
|
||||
public void loadNCFile() {
|
||||
LOGGER.debug("loadNCFile");
|
||||
|
||||
String fileAdd = getNCFile();
|
||||
if (fileAdd != null && !fileAdd.isEmpty()) {
|
||||
LOGGER.debug("NCFile path = " + fileAdd);
|
||||
|
||||
File file = new File(fileAdd);
|
||||
if (!file.exists()) {
|
||||
LOGGER.warn("file not exists!");
|
||||
KeyValueDBUtil.instance.setValue(NCTables.NCFile.toString(), "filePath", "");
|
||||
return;
|
||||
}
|
||||
|
||||
String keyPairStr = null;
|
||||
try {
|
||||
FileReader fr = new FileReader(file);
|
||||
BufferedReader br = new BufferedReader(fr);
|
||||
String s;
|
||||
while (null != (s = br.readLine())) {
|
||||
keyPairStr = s;
|
||||
}
|
||||
fr.close();
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (keyPairStr == null) {
|
||||
LOGGER.warn("import ket pair form NCFile is null!");
|
||||
return;
|
||||
}
|
||||
LOGGER.info("import ket pair from NCFile : " + keyPairStr);
|
||||
sm2 = SM2KeyPair.fromJson(keyPairStr);
|
||||
} else {
|
||||
sm2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getOtherNCs() {
|
||||
return KeyValueDBUtil.instance.getValue(NCTables.OtherNCs.toString(), "address");
|
||||
}
|
||||
|
||||
public String getNCFile() {
|
||||
return KeyValueDBUtil.instance.getValue(NCTables.NCFile.toString(), "filePath");
|
||||
}
|
||||
|
||||
//配置其他NC
|
||||
public String setOtherNCs(String add) {
|
||||
LOGGER.debug("setOtherNC: " + add);
|
||||
|
||||
KeyValueDBUtil.instance.setValue(NCTables.OtherNCs.toString(), "address", add);
|
||||
loadOtherNCs();
|
||||
return getOtherNCs();
|
||||
}
|
||||
|
||||
//配置NC文件
|
||||
public String setNCFile(String fileName) {
|
||||
LOGGER.debug("setNCFIle: " + fileName);
|
||||
|
||||
KeyValueDBUtil.instance.setValue(NCTables.NCFile.toString(), "filePath", fileName);
|
||||
loadNCFile();
|
||||
return getNCFile();
|
||||
}
|
||||
|
||||
//本地更新
|
||||
public void updateOtherNCInfo(String nodePubkey, List<OtherNCInfo> list) {
|
||||
LOGGER.debug("updateOtherNCInfo: ");
|
||||
|
||||
synchronized (otherNodeCenterInfos) {
|
||||
otherNodeCenterInfos.put(nodePubkey, list);
|
||||
LOGGER.debug("update route nodePubkey=" + nodePubkey + " list=" + JsonUtil.toJson(list));
|
||||
}
|
||||
}
|
||||
|
||||
//通过合约id或name在别的nc上查询信息
|
||||
public String search(String id) {
|
||||
LOGGER.debug("search : " + id);
|
||||
synchronized (otherNodeCenterInfos) {
|
||||
for (String pubKey : otherNodeCenterInfos.keySet()) {
|
||||
List<OtherNCInfo> list = otherNodeCenterInfos.get(pubKey);
|
||||
for (OtherNCInfo info : list) {
|
||||
if (info.contractID.equals(id) || info.contractName.equals(id)) {
|
||||
LOGGER.debug("[OtherNCProxy] find contract " + id + "pubKey is " + pubKey + " master is " + info.master + " from other NC route info");
|
||||
return pubKey + ";" + info.master;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//向其他NC发起同步
|
||||
public void requestUpdate() {
|
||||
LOGGER.debug("sendUpdate: ");
|
||||
for (String add : instance.ncAdds) {
|
||||
try {
|
||||
instance.connectToNC(add);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("NC " + add + " can not be connected! " + e.getMessage());
|
||||
connList.get(add).close();
|
||||
continue;
|
||||
}
|
||||
JsonObject args = new JsonObject();
|
||||
args.addProperty("action", "requestRouteInfo");
|
||||
args.addProperty("address", add);
|
||||
connList.get(add).sendMsg(JsonUtil.toJson(args));
|
||||
}
|
||||
}
|
||||
|
||||
public List<OtherNCInfo> getInfo() {
|
||||
LOGGER.debug("getInfo: ");
|
||||
|
||||
List<OtherNCInfo> list = new ArrayList<>();
|
||||
for (Map.Entry<String, CMNode> stringCMNodeEntry : NodeCenterActions.nodeInfos.entrySet()) {
|
||||
CMNode node = stringCMNodeEntry.getValue();
|
||||
if (null == node.contracts)
|
||||
continue;
|
||||
for (ContractDesp desp : node.contracts) {
|
||||
if (desp.type == ContractExecType.Sole || desp.getIsMaster()) {
|
||||
list.add(new OtherNCInfo(desp.contractID, desp.contractName, node.masterAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void connectToNC(String target) throws InterruptedException {
|
||||
LOGGER.debug("connectToNC: ");
|
||||
if (target == null || !target.contains(":")) {
|
||||
LOGGER.error("connectToNC failed, target nc address is illegal! target=" + target);
|
||||
return;
|
||||
}
|
||||
|
||||
final Bootstrap b = new Bootstrap();
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
b.group(group);
|
||||
NCConnector conn = new NCConnector(target, b, new NCClientHandler());
|
||||
connList.put(target, conn);
|
||||
b.channel(NioSocketChannel.class)
|
||||
.handler(
|
||||
new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) {
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
p.addLast(new DelimiterCodec()).addLast(conn.handler);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (!conn.handler.isOpen()) {
|
||||
String[] ipAndPort = target.split(":");
|
||||
b.connect(ipAndPort[0], Integer.parseInt(ipAndPort[1]))
|
||||
.sync()
|
||||
.channel();
|
||||
}
|
||||
|
||||
reconnect(target);
|
||||
}
|
||||
|
||||
public void reconnect(String target) throws InterruptedException {
|
||||
LOGGER.debug("reconnect: ");
|
||||
|
||||
if (!connList.containsKey(target))
|
||||
return;
|
||||
|
||||
NCConnector conn = connList.get(target);
|
||||
if (!conn.handler.isOpen()) {
|
||||
String[] ipAndPort = conn.ipAndPort.split(":");
|
||||
conn.bootstrap
|
||||
.connect(ipAndPort[0], Integer.parseInt(ipAndPort[1]))
|
||||
.sync()
|
||||
.channel();
|
||||
}
|
||||
}
|
||||
|
||||
static class NCConnector {
|
||||
Bootstrap bootstrap;
|
||||
NCClientHandler handler;
|
||||
String ipAndPort;
|
||||
|
||||
public NCConnector(String s, Bootstrap b, NCClientHandler h) {
|
||||
bootstrap = b;
|
||||
handler = h;
|
||||
ipAndPort = s;
|
||||
}
|
||||
|
||||
public void sendMsg(String s) {
|
||||
handler.sendMsg(s);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
handler.close();
|
||||
OtherNCProxy.instance.connList.remove(ipAndPort);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonArray;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.server.action.Action;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class TracingAction {
|
||||
private static JsonObject getDependentContract(JsonObject jo) {
|
||||
//考虑多层依赖
|
||||
JsonObject result = new JsonObject();
|
||||
JsonArray beDependent = new JsonArray();
|
||||
String contractName = jo.get("contractName").getAsString();
|
||||
try {
|
||||
if (!jo.has("contractName")) {
|
||||
result.addProperty("exception", "missing arguments: contractName");
|
||||
return result;
|
||||
}
|
||||
JsonArray dependencies = new JsonArray();
|
||||
for (CMNode node : NodeCenterActions.nodeInfos.values()) {
|
||||
for (ContractDesp desp : node.contracts) {
|
||||
if (desp.contractName.equals(contractName)) {
|
||||
if (desp.dependentContracts != null) {
|
||||
for (String val : desp.dependentContracts)
|
||||
dependencies.add(val);
|
||||
}
|
||||
} else {
|
||||
if (desp.dependentContracts != null && desp.dependentContracts.contains(contractName)) {
|
||||
beDependent.add(desp.contractName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.add("dependencies", dependencies);
|
||||
result.add("beDependent", beDependent);
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
e.printStackTrace(new PrintStream(bo));
|
||||
result.addProperty("exception", bo.toString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Action(async = true)
|
||||
public void getDependentContract(JsonObject json, ResultCallback rc) {
|
||||
JsonObject result = getDependentContract(json);
|
||||
JsonObject jo = new JsonObject();
|
||||
if (json.has("requestID"))
|
||||
jo.add("responseID", json.get("requestID"));
|
||||
jo.add("result", result);
|
||||
jo.addProperty("action", "onGetDependentContract");
|
||||
rc.onResult(jo.toString());
|
||||
}
|
||||
}
|
407
src/main/java/org/bdware/server/nodecenter/UnitActions.java
Normal file
407
src/main/java/org/bdware/server/nodecenter/UnitActions.java
Normal file
@ -0,0 +1,407 @@
|
||||
package org.bdware.server.nodecenter;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.sc.Jedion.KV;
|
||||
import org.bdware.sc.bean.ContractDesp;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.sc.db.KeyValueDBUtil;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.bdware.server.action.Action;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class UnitActions {
|
||||
private static final Logger LOGGER = LogManager.getLogger(UnitActions.class);
|
||||
private final NCManagerAction managerAction;
|
||||
|
||||
public UnitActions(NCManagerAction managerAction) {
|
||||
this.managerAction = managerAction;
|
||||
}
|
||||
|
||||
private static String convertContractName(String contractID) {
|
||||
ContractDesp desp = NodeCenterActions.getContractByName(contractID);
|
||||
if (desp != null) return desp.contractID;
|
||||
return contractID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示当前用户可见的集群
|
||||
*
|
||||
* @param json
|
||||
* @param resultCallback
|
||||
*/
|
||||
@Action(userPermission = 1 << 6, async = true)
|
||||
public void listTrustUnits(JsonObject json, ResultCallback resultCallback) {
|
||||
long start = System.currentTimeMillis();
|
||||
final String pubKey = managerAction.pubKey;
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
List<KV> allunits = KeyValueDBUtil.instance.getKeyValues(NCTables.TrustUnitsDB.toString());
|
||||
|
||||
if (pubKey != null
|
||||
&& KeyValueDBUtil.instance
|
||||
.getValue(NCTables.ConfigDB.toString(), "__CenterManager__")
|
||||
.contains(pubKey)) {
|
||||
LOGGER.debug("is center manager");
|
||||
ret.put("action", "onListTrustUnits");
|
||||
ret.put("data", allunits);
|
||||
LOGGER.debug("[listTrustUnits] " + JsonUtil.toJson(ret));
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listTrustUnits:time]" + (end - start));
|
||||
return;
|
||||
}
|
||||
// 合约管理者获取自己创建的units
|
||||
Iterator<KV> it = allunits.iterator();
|
||||
List<KV> ciunits = new ArrayList<>();
|
||||
while (it.hasNext()) {
|
||||
KV kv = it.next();
|
||||
if (kv.key.contains(pubKey)) {
|
||||
ciunits.add(kv);
|
||||
}
|
||||
}
|
||||
ret.put("action", "onListTrustUnits");
|
||||
ret.put("data", ciunits);
|
||||
LOGGER.debug("[listTrustUnits] " + JsonUtil.toJson(ret));
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
long end = System.currentTimeMillis();
|
||||
LOGGER.debug("[listTrustUnits:time]" + (end - start));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 6, async = true)
|
||||
public void createTrustUnit(JsonObject json, ResultCallback resultCallback) {
|
||||
final String pubKey = managerAction.pubKey;
|
||||
LOGGER.debug("[createTrustUnit] " + json.get("data").toString());
|
||||
KeyValueDBUtil.instance.setValue(
|
||||
NCTables.TrustUnitsDB.toString(),
|
||||
pubKey + "_" + json.get("msg").getAsString(),
|
||||
json.get("data").toString());
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("action", "onCreateTrustUnit");
|
||||
ret.put("status", "Success");
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 6, async = true)
|
||||
public void deleteTrustUnit(JsonObject json, ResultCallback resultCallback) {
|
||||
// final String pubKey = managerAction.pubKey;
|
||||
LOGGER.debug(
|
||||
"[deleteTrustUnit] before"
|
||||
+ KeyValueDBUtil.instance.getValue(
|
||||
NCTables.TrustUnitsDB.toString(), json.get("data").getAsString()));
|
||||
KeyValueDBUtil.instance.delete(
|
||||
NCTables.TrustUnitsDB.toString(), json.get("data").getAsString());
|
||||
LOGGER.debug(
|
||||
"[deleteTrustUnit] after"
|
||||
+ KeyValueDBUtil.instance.getValue(
|
||||
NCTables.TrustUnitsDB.toString(), json.get("data").getAsString()));
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("action", "onDeleteTrustUnit");
|
||||
ret.put("status", "Success");
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
// @Action(async = true)
|
||||
// public void executeContract(JsonObject args, final ResultCallback rc) {
|
||||
// executeContractTrustfully(args, rc);
|
||||
// }
|
||||
|
||||
@Action(async = true, userPermission = 1L << 6)
|
||||
public void getNodeTrustUnits(JsonObject json, ResultCallback resultCallback) {
|
||||
String nodeID = json.get("data").getAsString();
|
||||
List<KV> allunits = KeyValueDBUtil.instance.getKeyValues(NCTables.TrustUnitsDB.toString());
|
||||
Iterator<KV> it = allunits.iterator();
|
||||
List<KV> nodeunits = new ArrayList<KV>();
|
||||
while (it.hasNext()) {
|
||||
KV kv = it.next();
|
||||
if (kv.value.contains(nodeID)) {
|
||||
nodeunits.add(kv);
|
||||
}
|
||||
}
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("action", "onGetNodeTrustUnits");
|
||||
ret.put("data", nodeunits);
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
// @Action(async = true, userPermission = 0)
|
||||
// public void executeContractTrustfully(JsonObject args, final ResultCallback rc) {
|
||||
// String contractID = args.get("contractID").getAsString();
|
||||
//
|
||||
// contractID = convertContractName(contractID);
|
||||
//
|
||||
// args.remove("contractID");
|
||||
// args.addProperty("contractID", contractID);
|
||||
// String requestID;
|
||||
// if (!args.has("requestID")) {
|
||||
// requestID = System.currentTimeMillis() + "_" + (int) (Math.random() * 10000);
|
||||
// args.addProperty("requestID", requestID);
|
||||
// } else requestID = args.get("requestID").getAsString();
|
||||
// args.remove("action");
|
||||
// args.addProperty("action", "executeContractTrustfully");
|
||||
// MultiPointContractInfo mInfo = NodeCenterActions.contractID2Members.get(contractID);
|
||||
// args.addProperty("seq", mInfo.getNextSeq());
|
||||
// args.addProperty("needSeq", ContractType.needSeq(mInfo.type));
|
||||
// List<String> nodes = mInfo.members;
|
||||
// logger.debug("tid:" + Thread.currentThread().getId() + " contractID:" + contractID);
|
||||
// if (nodes == null) {
|
||||
// rc.onResult(
|
||||
// "{\"status\":\"Error\",\"result\":\"can't locate contract\",\"action\":\"onExecuteContractTrustfully\"}");
|
||||
// } else {
|
||||
// mInfo.rcf.execute(requestID, rc, JsonUtil.toJson(args));
|
||||
// }
|
||||
//
|
||||
// // add request cache,only for requestAll type contract
|
||||
// if (ContractType.needSeq(mInfo.type)) {
|
||||
// RequestCache reqc = NodeCenterActions.getCache(contractID);
|
||||
// reqc.put(args.get("seq").getAsString(), args);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
//only for test ADSP
|
||||
// public static void testExecuteContract(JsonObject args, final ResultCallback rc) {
|
||||
// String contractID = args.get("contractID").getAsString();
|
||||
//
|
||||
// contractID = convertContractName(contractID);
|
||||
//
|
||||
// args.remove("contractID");
|
||||
// args.addProperty("contractID", contractID);
|
||||
// String requestID;
|
||||
// if (!args.has("requestID")) {
|
||||
// requestID = System.currentTimeMillis() + "_" + (int) (Math.random() * 10000);
|
||||
// args.addProperty("requestID", requestID);
|
||||
// } else requestID = args.get("requestID").getAsString();
|
||||
// args.remove("action");
|
||||
// args.addProperty("action", "executeContractTrustfully");
|
||||
// MultiPointContractInfo mInfo = NodeCenterActions.contractID2Members.get(contractID);
|
||||
// System.out.println("mInfo是空吗?" + mInfo == null);
|
||||
//
|
||||
// args.addProperty("seq", mInfo.getNextSeq());
|
||||
// args.addProperty("needSeq", ContractType.needSeq(mInfo.type));
|
||||
// List<String> nodes = mInfo.members;
|
||||
// logger.debug("tid:" + Thread.currentThread().getId() + " contractID:" + contractID);
|
||||
// if (nodes == null) {
|
||||
// rc.onResult(
|
||||
// "{\"status\":\"Error\",\"result\":\"can't locate contract\",\"action\":\"onExecuteContractTrustfully\"}");
|
||||
// } else {
|
||||
// mInfo.rcf.execute(requestID, rc, JsonUtil.toJson(args));
|
||||
// }
|
||||
//
|
||||
// //add request cache,only for requestAll type contract
|
||||
// if(ContractType.needSeq(mInfo.type)){
|
||||
// RequestCache reqc = NodeCenterActions.getCache(contractID);
|
||||
// reqc.put(args.get("seq").getAsString(),args);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Action(async = true, userPermission = 1L << 6)
|
||||
public void listContractProcess(JsonObject args, final ResultCallback rc) {
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("action", "onListContractProcess");
|
||||
List<ContractDesp> info = new ArrayList<>();
|
||||
LOGGER.debug(
|
||||
"[contracts] "
|
||||
+ JsonUtil.toPrettyJson(NodeCenterActions.nodeInfos));
|
||||
LOGGER.debug(
|
||||
"[cid2Nodes]"
|
||||
+ JsonUtil.toPrettyJson(NodeCenterActions.contractID2Members));
|
||||
for (String key : NodeCenterActions.contractID2Members.keySet()) {
|
||||
ContractDesp desp = NodeCenterActions.getContractByID(key);
|
||||
if (desp != null) info.add(desp);
|
||||
}
|
||||
ret.put("data", JsonUtil.toJson(info));
|
||||
rc.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 6, async = true)
|
||||
public void listMultiPointContractProcess(JsonObject json, ResultCallback resultCallback) {
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("action", "onListMultiPointContractProcess");
|
||||
List<ContractDesp> info = new ArrayList<>();
|
||||
LOGGER.debug(
|
||||
"[contracts] "
|
||||
+ JsonUtil.toPrettyJson(NodeCenterActions.nodeInfos));
|
||||
LOGGER.debug(
|
||||
"[cid2Nodes]"
|
||||
+ JsonUtil.toPrettyJson(NodeCenterActions.contractID2Members));
|
||||
for (String key : NodeCenterActions.contractID2Members.keySet()) {
|
||||
ContractDesp desp = NodeCenterActions.getContractByID(key);
|
||||
if (desp != null) info.add(desp);
|
||||
}
|
||||
ret.put("data", JsonUtil.toJson(info));
|
||||
resultCallback.onResult(JsonUtil.toJson(ret));
|
||||
}
|
||||
|
||||
@Action(userPermission = 1 << 6, async = true)
|
||||
public void stopMultiPointContractProcess(JsonObject json, ResultCallback resultCallback) {
|
||||
String contractID = json.get("contractID").getAsString();
|
||||
MultiPointContractInfo info = NodeCenterActions.contractID2Members.get(contractID);
|
||||
NodeCenterActions.contractID2Members.remove(contractID);
|
||||
String req = "{\"action\":\"killContractProcess\",\"contractID\":\"" + contractID + "\"}";
|
||||
for (String member : info.members) {
|
||||
CMNode node;
|
||||
node = NodeCenterActions.nodeInfos.get(member);
|
||||
node.connection.controller.sendMsg(req);
|
||||
}
|
||||
listMultiPointContractProcess(json, resultCallback);
|
||||
}
|
||||
|
||||
// @Action(async = true, userPermission = 1L << 6)
|
||||
// public void startContractMultiPoint(JsonObject args, final ResultCallback rc) {
|
||||
// Map<String, String> request = new HashMap<String, String>();
|
||||
// Contract contract = new Contract();
|
||||
// if (args.has("type")) {
|
||||
// contract.setType(ContractType.valueOf(args.get("type").getAsString()));
|
||||
// }
|
||||
//
|
||||
// // this multiPointContractInfo problem
|
||||
// MultiPointContractInfo multiPointContractInfo = new MultiPointContractInfo();
|
||||
// multiPointContractInfo.type = contract.getType();
|
||||
//
|
||||
// logger.debug("startContractMultiPoint:");
|
||||
// logger.debug(JsonUtil.toPrettyJson(args));
|
||||
// if (args.has("script")) contract.setScript(args.get("script").getAsString());
|
||||
// else if (args.has("path")) contract.setScript(args.get("path").getAsString());
|
||||
// else if (args.has("projectName"))
|
||||
// contract.setScript("/" + args.get("projectName").getAsString());
|
||||
// // contract.setScript("/" + args.get("projectName").getAsString() + "/manifest.json");
|
||||
//
|
||||
// SM2 sm2 = new SM2();
|
||||
// SM2KeyPair sm2Key = sm2.generateKeyPair();
|
||||
// contract.setID(sm2Key.getPublicKeyStr().hashCode() + "");
|
||||
// contract.setKey(sm2Key.getPrivateKey().toString(16));
|
||||
// contract.setPublicKey(sm2Key.getPublicKeyStr());
|
||||
//
|
||||
// contract.setNodeCenterRepoDOI(DOIPMainServer4NC.repoIdentifier);
|
||||
// // 多点合约部署时,由NC预先注册一个DOI以备使用
|
||||
// if (DoConfig.openContractDORegister) {
|
||||
// try {
|
||||
// HandleService hs = new HandleService(HandleServiceUtils.hrRegister);
|
||||
// String tmpDOI = hs.registerContract(DOIPMainServer4NC.repoIdentifier);
|
||||
// if (tmpDOI == "" || tmpDOI == null)
|
||||
// contract.setDOI("RegisterFailed");
|
||||
// else
|
||||
// contract.setDOI(tmpDOI);
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// contract.setDOI("RegisterFailed");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// String[] nodeNames =
|
||||
// args.get("peersID").getAsString().split(","); // all nodes' peerID in the unit
|
||||
// Set<String> nodeNameSet = new HashSet<>(); // nodes' peerID
|
||||
// for (String str : nodeNames) {
|
||||
// if (str != null && str.length() > 0) nodeNameSet.add(str);
|
||||
// }
|
||||
//
|
||||
// List<String> udpids = new ArrayList<>(); // nodes' udpID in the unit
|
||||
//
|
||||
// for (CMNode node : NodeCenterActions.nodeinfos.values()) {
|
||||
// if (nodeNameSet.contains(node.nodeName)) {
|
||||
// udpids.add(node.udpID);
|
||||
// }
|
||||
// }
|
||||
// final long curr = System.currentTimeMillis();
|
||||
// String requestID = curr + "_" + (int) (Math.random() * 10000);
|
||||
// NodeCenterActions.ResultCollector collector =
|
||||
// new NodeCenterActions.ResultCollector(
|
||||
// requestID,
|
||||
// new ResultCallback() {
|
||||
// @Override
|
||||
// public void onResult(String str) {
|
||||
// Map<String, String> ret = new HashMap<>();
|
||||
// ret.put("action", "onStartContractTrustfullyResult");
|
||||
// ret.put("data", str);
|
||||
// ret.put("executionTime", (System.currentTimeMillis() - curr) + "");
|
||||
// rc.onResult(JsonUtil.toJson(ret));
|
||||
// }
|
||||
// },
|
||||
// udpids.size());
|
||||
// NodeCenterActions.sync.sleepWithTimeout(requestID, collector, 20);
|
||||
//
|
||||
// // ArrayList<String> udpids=gson.fromJson(args.get("members"),
|
||||
// // new TypeToken<ArrayList<String>>(){}.getType());
|
||||
// Map<String, String> members = new HashMap<>(); // nodes' <udpID,udpAddress>
|
||||
// for (int i = 0; i < udpids.size(); i++) {
|
||||
// members.put(
|
||||
// udpids.get(i),
|
||||
// NodeCenterActions.runner.getUDPAddr(Integer.valueOf(udpids.get(i)))
|
||||
// + ":"
|
||||
// + (i == 0)); // regard the first node as the master in the unit
|
||||
// }
|
||||
//
|
||||
// List<String> nodes = new ArrayList<>(); // nodes' pubKey
|
||||
// for (CMNode node : NodeCenterActions.nodeinfos.values()) {
|
||||
// if (nodeNameSet.contains(node.nodeName)) {
|
||||
// nodes.add(node.pubKey);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// request.put("memberStr", JsonUtil.toJson(members));
|
||||
// request.put("isPrivate", args.get("isPrivate").getAsString());
|
||||
// request.put("pubKey", managerAction.pubKey);
|
||||
// request.put("action", "startContractTrustfully");
|
||||
// request.put("requestID", requestID);
|
||||
// multiPointContractInfo.members = nodes;
|
||||
//
|
||||
// contract.setNumOfCopies(1);
|
||||
// switch (multiPointContractInfo.type) {
|
||||
// case Sole:
|
||||
// logger.debug("Can't support Solo in multi-point mode");
|
||||
// return;
|
||||
// case RequestOnce:
|
||||
// multiPointContractInfo.rcf = new RequestOnceExecutor(multiPointContractInfo);
|
||||
// break;
|
||||
// case ResponseOnce:
|
||||
// multiPointContractInfo.rcf = new ResponseOnceExecutor(multiPointContractInfo);
|
||||
// break;
|
||||
// case RequestAllResponseFirst:
|
||||
// multiPointContractInfo.rcf = new RequestAllExecutor(multiPointContractInfo, 1);
|
||||
// contract.setNumOfCopies(nodes.size());
|
||||
// break;
|
||||
// case RequestAllResponseHalf:
|
||||
// multiPointContractInfo.rcf =
|
||||
// new RequestAllExecutor(multiPointContractInfo, nodes.size() / 2 + 1);
|
||||
// contract.setNumOfCopies(nodes.size());
|
||||
// break;
|
||||
// case RequestAllResponseAll:
|
||||
// multiPointContractInfo.rcf =
|
||||
// new RequestAllExecutor(multiPointContractInfo, nodes.size());
|
||||
// contract.setNumOfCopies(nodes.size());
|
||||
// break;
|
||||
// }
|
||||
// NodeCenterActions.contractID2Members.put(contract.getID(), multiPointContractInfo);
|
||||
//
|
||||
// request.put("contractStr", JsonUtil.toJson(contract));
|
||||
// String startReq = JsonUtil.toJson(request);
|
||||
// logger.debug("启动合约:" + startReq);
|
||||
//
|
||||
// for (String nodeID : nodes) {
|
||||
// CMNode node;
|
||||
// node = NodeCenterActions.nodeinfos.get(nodeID);
|
||||
// node.connection.controller.sendMsg(startReq);
|
||||
//
|
||||
// if (!NodeCenterActions.recoverMap.containsKey(nodeID)) {
|
||||
// NodeCenterActions.recoverMap.put(nodeID, new ConcurrentHashMap<>());
|
||||
// }
|
||||
// ContractRecord record = new ContractRecord(contract.getID());
|
||||
// record.members = new HashMap<>(members);
|
||||
// NodeCenterActions.recoverMap.get(nodeID).put(contract.getID(), record);
|
||||
// }
|
||||
//
|
||||
// rc.onResult(
|
||||
// "{\"status\":\"Success\",\"result\":\""
|
||||
// + contract.getID()
|
||||
// + "\",\"action\":\"onStartTrustfulContract\"}");
|
||||
// }
|
||||
|
||||
private void example() {
|
||||
for (CMNode node : NodeCenterActions.nodeInfos.values()) {
|
||||
// node.connection.executeContractTrustfully(args, rc);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package org.bdware.server.nodecenter.searchresult;
|
||||
|
||||
public class ContractMeta {
|
||||
private String contractID;
|
||||
private String name;
|
||||
private String status;
|
||||
private String pubkey;
|
||||
private String owner;
|
||||
private String readmeStr;
|
||||
private String nodeAddr;
|
||||
private String pngUrl;
|
||||
private String doi;
|
||||
private long buildTime;
|
||||
private String doip;
|
||||
|
||||
|
||||
public String getContractID() {
|
||||
return contractID;
|
||||
}
|
||||
|
||||
public void setContractID(String contractID) {
|
||||
this.contractID = contractID;
|
||||
}
|
||||
|
||||
public String getPubkey() {
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
public void setPubkey(String pubkey) {
|
||||
this.pubkey = pubkey;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getReadmeStr() {
|
||||
return readmeStr;
|
||||
}
|
||||
|
||||
public void setReadmeStr(String readmeStr) {
|
||||
this.readmeStr = readmeStr;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getNodeAddr() {
|
||||
return nodeAddr;
|
||||
}
|
||||
|
||||
public void setNodeAddr(String nodeAddr) {
|
||||
this.nodeAddr = nodeAddr;
|
||||
}
|
||||
|
||||
public String getPngUrl() {
|
||||
return pngUrl;
|
||||
}
|
||||
|
||||
public void setPngUrl(String pngUrl) {
|
||||
this.pngUrl = pngUrl;
|
||||
}
|
||||
|
||||
public String getDoi() {
|
||||
return doi;
|
||||
}
|
||||
|
||||
public void setDoi(String doi) {
|
||||
this.doi = doi;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getBuildTime() {
|
||||
return buildTime;
|
||||
}
|
||||
|
||||
public void setBuildTime(long buildTime) {
|
||||
this.buildTime = buildTime;
|
||||
}
|
||||
|
||||
public String getDoip() {
|
||||
return doip;
|
||||
}
|
||||
|
||||
public void setDoip(String doip) {
|
||||
this.doip = doip;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package org.bdware.server.nodecenter.searchresult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ResultModel {
|
||||
private List<ContractMeta> contractMetaList;
|
||||
private Long contractCount;
|
||||
private Long pageCount;
|
||||
private long curPage;
|
||||
|
||||
public List<ContractMeta> getContractMetaList() {
|
||||
return contractMetaList;
|
||||
}
|
||||
|
||||
public void setContractMetaList(List<ContractMeta> contractMetaList) {
|
||||
this.contractMetaList = contractMetaList;
|
||||
}
|
||||
|
||||
public Long getContractCount() {
|
||||
return contractCount;
|
||||
}
|
||||
|
||||
public void setContractCount(Long contractCount) {
|
||||
this.contractCount = contractCount;
|
||||
}
|
||||
|
||||
public Long getPageCount() {
|
||||
return pageCount;
|
||||
}
|
||||
|
||||
public void setPageCount(Long pageCount) {
|
||||
this.pageCount = pageCount;
|
||||
}
|
||||
|
||||
public long getCurPage() {
|
||||
return curPage;
|
||||
}
|
||||
|
||||
public void setCurPage(long curPage) {
|
||||
this.curPage = curPage;
|
||||
}
|
||||
}
|
8
src/main/resources/log4j.properties
Normal file
8
src/main/resources/log4j.properties
Normal file
@ -0,0 +1,8 @@
|
||||
### 设置###
|
||||
log4j.rootLogger = info,debug,stdout
|
||||
|
||||
### 输出信息到控制抬 ###
|
||||
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.Target = System.out
|
||||
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{HH:mm:ss.SSS} %m (%F:%L)[%M]%n
|
15
src/main/resources/log4j2.properties
Normal file
15
src/main/resources/log4j2.properties
Normal file
@ -0,0 +1,15 @@
|
||||
filter.threshold.type=ThresholdFilter
|
||||
filter.threshold.level=debug
|
||||
appender.console.type=Console
|
||||
appender.console.name=STDOUT
|
||||
appender.console.layout.type=PatternLayout
|
||||
appender.console.layout.pattern=%highlight{[%-5p] %d{HH:mm:ss.SSS} %m (%F:%L)[%M]%n}{FATAL=Bright Red,ERROR=Red,WARN=Yellow,INFO=Green,DEBUG=Blue,TRACE=White}
|
||||
appender.rolling.type=File
|
||||
appender.rolling.name=log
|
||||
appender.rolling.append=true
|
||||
appender.rolling.fileName=./log/nc.log
|
||||
appender.rolling.layout.type=PatternLayout
|
||||
appender.rolling.layout.pattern=%d-%m%n
|
||||
rootLogger.level=info
|
||||
rootLogger.appenderRef.stdout.ref=STDOUT
|
||||
rootLogger.appenderRef.log.ref=log
|
63
src/main/resources/org/bdware/server/stopwords.txt
Normal file
63
src/main/resources/org/bdware/server/stopwords.txt
Normal file
@ -0,0 +1,63 @@
|
||||
////////// Punctuation tokens to remove ////////////////
|
||||
,
|
||||
.
|
||||
`
|
||||
-
|
||||
_
|
||||
=
|
||||
?
|
||||
'
|
||||
|
|
||||
"
|
||||
(
|
||||
)
|
||||
{
|
||||
}
|
||||
[
|
||||
]
|
||||
<
|
||||
>
|
||||
*
|
||||
#
|
||||
&
|
||||
^
|
||||
$
|
||||
@
|
||||
!
|
||||
~
|
||||
:
|
||||
;
|
||||
+
|
||||
/
|
||||
\
|
||||
《
|
||||
》
|
||||
—
|
||||
-
|
||||
,
|
||||
。
|
||||
、
|
||||
:
|
||||
;
|
||||
!
|
||||
·
|
||||
?
|
||||
“
|
||||
”
|
||||
)
|
||||
(
|
||||
【
|
||||
】
|
||||
[
|
||||
]
|
||||
●
|
||||
// the line below contains an IDEOGRAPHIC SPACE character (Used as a space in Chinese)
|
||||
|
||||
|
||||
//////////////// English Stop Words ////////////////
|
||||
|
||||
//////////////// Chinese Stop Words ////////////////
|
||||
的
|
||||
我
|
||||
是
|
||||
想
|
127
src/test/java/org/bdware/bdserver/IRPTest.java
Normal file
127
src/test/java/org/bdware/bdserver/IRPTest.java
Normal file
@ -0,0 +1,127 @@
|
||||
package org.bdware.bdserver;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bdware.doip.core.exception.IrpClientException;
|
||||
import org.bdware.doip.core.model.handleRecord.DoHandleRecord;
|
||||
import org.bdware.doip.core.model.handleRecord.DoipServiceHandleRecord;
|
||||
import org.bdware.doip.core.model.handleRecord.HandleRecordBase;
|
||||
import org.bdware.doip.core.utils.GlobalConfigurations;
|
||||
import org.bdware.doip.endpoint.irpClient.InternalIrpClient;
|
||||
import org.bdware.doip.endpoint.irpClient.IrpClient;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class IRPTest {
|
||||
private static final Logger LOGGER = LogManager.getLogger(IRPTest.class);
|
||||
IrpClient client;
|
||||
|
||||
@Before
|
||||
public void createTestClient() {
|
||||
GlobalConfigurations.LHS_Address = "http://127.0.0.1:18007/";
|
||||
client = new InternalIrpClient(null, "86.5000.470/dou.SUPER", GlobalConfigurations.LHS_Address);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReslove() {
|
||||
HandleRecordBase handleRecordBase = null;
|
||||
try {
|
||||
handleRecordBase = client.resolve("86.5000.470/doip.iZWUqzwFtY_bdw");
|
||||
} catch (IrpClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LOGGER.info(new Gson().toJson(handleRecordBase));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister() {
|
||||
DoHandleRecord doHr = new DoHandleRecord(GlobalConfigurations.User_Handle, "null");
|
||||
DoipServiceHandleRecord doipServiceHandleRecord = new DoipServiceHandleRecord("1", "2", "3", "4", "5");
|
||||
String handle = "86.5000.470/do.yWkNN8otdv_bdw";
|
||||
// doHr.handle = handle;
|
||||
try {
|
||||
handle = client.register(doipServiceHandleRecord);
|
||||
LOGGER.debug(handle);
|
||||
//test resolve
|
||||
HandleRecordBase handleRecordBase = client.resolve(handle);
|
||||
LOGGER.info(new Gson().toJson(handleRecordBase));
|
||||
} catch (IrpClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregister() {
|
||||
String handle = "86.5000.470/do.A0gOqH2hup_bdw";
|
||||
String resp = client.unRegister(handle);
|
||||
LOGGER.info(resp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReRegister() {
|
||||
DoHandleRecord doHr = new DoHandleRecord(GlobalConfigurations.User_Handle, "12345");
|
||||
String handle = "86.5000.470/do.Y1LnYqyH5F_bdw";
|
||||
doHr.handle = handle;
|
||||
try {
|
||||
handle = client.reRegister(doHr);
|
||||
LOGGER.debug(handle);
|
||||
//test resolve
|
||||
HandleRecordBase handleRecordBase = client.resolve(handle);
|
||||
LOGGER.debug(new Gson().toJson(handleRecordBase));
|
||||
} catch (IrpClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pumpDataIntoLhs() {
|
||||
DoHandleRecord doHr = new DoHandleRecord(GlobalConfigurations.User_Handle, "null");
|
||||
DoipServiceHandleRecord doipServiceHandleRecord = new DoipServiceHandleRecord("1", "2", "3", "4", "5");
|
||||
String handle;
|
||||
// doHr.handle = handle;
|
||||
try {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
handle = client.register(doipServiceHandleRecord);
|
||||
LOGGER.info(handle);
|
||||
handle = client.register(doHr);
|
||||
LOGGER.info(handle);
|
||||
}
|
||||
// handle = client.register(doipServiceHandleRecord);
|
||||
// logger.debug(handle);
|
||||
// //test resolve
|
||||
// HandleRecordBase handleRecordBase = client.resolve(handle);
|
||||
// logger.info(new Gson().toJson(handleRecordBase));
|
||||
} catch (IrpClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void updateUserHandleRecord(){
|
||||
// if (Security.getProvider("BC") == null) {
|
||||
// Security.addProvider(new BouncyCastleProvider());
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// GlobalCertifications.loadKeysFromJKS("keys/dou.SUPER.keystore", GlobalConfigurations.certPassword);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// GlobalIrpClient.useGeneralIrpClient(GlobalCertifications.localKeypair
|
||||
// , GlobalConfigurations.User_Handle
|
||||
// , GlobalConfigurations.LHS_Address);
|
||||
//
|
||||
// UserHandleRecord usr = new UserHandleRecord(JWK.getJWKFormatPK(GlobalCertifications.getGlobalKeypair().getPublic()),"SUPER USER");
|
||||
// usr.handle = "86.5000.470/dou.SUPER";
|
||||
// try {
|
||||
// String out = client.reRegister(usr);
|
||||
// logger.debug(out);
|
||||
// logger.debug("Resolution: " + client.resolve(usr.handle));
|
||||
// } catch (IrpClientException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
82
src/test/java/org/bdware/bdserver/PermissionHelper.java
Normal file
82
src/test/java/org/bdware/bdserver/PermissionHelper.java
Normal file
@ -0,0 +1,82 @@
|
||||
package org.bdware.bdserver;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.bdware.sc.conn.ResultCallback;
|
||||
import org.bdware.server.action.Action;
|
||||
import org.bdware.server.action.ActionExecutor;
|
||||
import org.bdware.server.nodecenter.NCHttpHandler;
|
||||
import org.bdware.server.nodecenter.NodeCenterWSFrameHandler;
|
||||
import org.bdware.server.permission.Role;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public class PermissionHelper {
|
||||
static class Line {
|
||||
String action;
|
||||
transient long permission;
|
||||
String roles;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listClusterHttpAction() {
|
||||
ActionExecutor<ResultCallback, JsonObject> ae = NCHttpHandler.getActionExecutor();
|
||||
Map<String, ActionExecutor.Pair<Method, Object>> handlers = ae.getHandlers();
|
||||
EnumSet<Role> set = EnumSet.allOf(Role.class);
|
||||
set.remove(Role.ContractInstanceManager);
|
||||
set.remove(Role.ContractProvider);
|
||||
set.remove(Role.ContractUser);
|
||||
printActions(handlers, set);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listClusterWSAction() {
|
||||
NodeCenterWSFrameHandler handler = new NodeCenterWSFrameHandler();
|
||||
Map<String, ActionExecutor.Pair<Method, Object>> handlers = handler.getAE().getHandlers();
|
||||
EnumSet<Role> set = EnumSet.allOf(Role.class);
|
||||
set.remove(Role.ContractInstanceManager);
|
||||
set.remove(Role.ContractProvider);
|
||||
set.remove(Role.ContractUser);
|
||||
|
||||
printActions(handlers, set);
|
||||
}
|
||||
|
||||
private void printActions(
|
||||
Map<String, ActionExecutor.Pair<Method, Object>> handlers, EnumSet<Role> set) {
|
||||
List<Line> lines = new ArrayList<>();
|
||||
for (String str : handlers.keySet()) {
|
||||
Method m = handlers.get(str).first();
|
||||
Action a = m.getAnnotation(Action.class);
|
||||
Line l = new Line();
|
||||
lines.add(l);
|
||||
l.action = str;
|
||||
l.permission = a.userPermission();
|
||||
l.roles = "";
|
||||
for (Role r : set)
|
||||
if ((r.getValue() & l.permission) == l.permission) l.roles += r.name() + ";";
|
||||
if (l.roles.equals("CenterManager;NodeManager;Node;Anonymous;")) l.roles = "任意角色";
|
||||
}
|
||||
lines.sort(
|
||||
new Comparator<Line>() {
|
||||
@Override
|
||||
public int compare(Line o1, Line o2) {
|
||||
return o1.action.compareTo(o2.action);
|
||||
}
|
||||
});
|
||||
lines.sort(
|
||||
new Comparator<Line>() {
|
||||
@Override
|
||||
public int compare(Line o1, Line o2) {
|
||||
return o1.roles.compareTo(o2.roles);
|
||||
}
|
||||
});
|
||||
|
||||
Gson g = new GsonBuilder().setPrettyPrinting().create();
|
||||
for (Line l : lines) {
|
||||
System.out.println("| " + l.action + " | | " + l.roles + " |");
|
||||
}
|
||||
}
|
||||
}
|
31
src/test/java/org/bdware/bdserver/TestServer.java
Normal file
31
src/test/java/org/bdware/bdserver/TestServer.java
Normal file
@ -0,0 +1,31 @@
|
||||
package org.bdware.bdserver;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class TestServer {
|
||||
private static final Logger LOGGER = LogManager.getLogger(TestServer.class);
|
||||
|
||||
static class TestHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
||||
TestHandler() {
|
||||
LOGGER.info("new instance");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
LOGGER.info("active");
|
||||
System.out.println("======Active=======");
|
||||
ctx.channel()
|
||||
.writeAndFlush("ACTIVE from Server")
|
||||
.addListener(future -> LOGGER.info("Active Send Done!!"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
|
||||
LOGGER.info("receive");
|
||||
}
|
||||
}
|
||||
}
|
192
src/test/java/org/bdware/bdserver/test/TestADSP.java
Normal file
192
src/test/java/org/bdware/bdserver/test/TestADSP.java
Normal file
@ -0,0 +1,192 @@
|
||||
package org.bdware.bdserver.test;
|
||||
|
||||
public class TestADSP {
|
||||
// public static Map<String,String> nodes = new HashMap<String,String>();
|
||||
//
|
||||
// private static volatile Boolean flag = false;
|
||||
// private static int totalRequest = 10;
|
||||
// private static int nodeCount = 5;
|
||||
//
|
||||
// public static String resultPath = "./testADSP/" + "result.txt";
|
||||
// public static String contractID = "counter";
|
||||
// public static String action = "executeContract";
|
||||
// public static String pubkey = "0480204f4ef341359a5f64fcb11baf9ca2e6706ac20cba36ca83066870cf2c1d5de6df67e24e68dde7934af9b31d94a6084281db3d32d5ce42ab8f75bf799aca05";
|
||||
//
|
||||
// public static String operation = "count";
|
||||
// public static String arg = "1";
|
||||
//
|
||||
// public static String priKey = "63464fa9587bbf2a022b3d655f4ed49c7d9a4249de1079d52bd5a1fec3308719";
|
||||
// public static String signature = "dfd07c00c5c89fb0f901bed132db4342f49f4560f34c15878636623d2a8716a2c93ad32eeb9ee9c4f1d905df292cb4a1a27aa0171f2856848ce07cfc8022e809";
|
||||
//
|
||||
// public static List<String> crashSeries = new ArrayList<String>();
|
||||
// public static AtomicInteger crashIndex = new AtomicInteger();
|
||||
//
|
||||
// public static ConcurrentSet<String> crashSet = new ConcurrentSet<String>();
|
||||
// public static ConcurrentSet<String> recover = new ConcurrentSet<String>();
|
||||
//
|
||||
// public static TestTask tt;
|
||||
// public static int period = 3000;
|
||||
//
|
||||
// static{
|
||||
// getSig();
|
||||
//
|
||||
// nodes.put("zyx's book","0440023d13facddcefbd87f2bb622b1b2b6ca43eb84c0579b82450814233ce557bd7ad7852cd47f1d6df867c5413ecf3dd1954cdbf5a6da683e3a89095f091d83d");
|
||||
// nodes.put("localNode1","0480f783cf63294224afbd19e175e5c7ea0c5c60ee115ed9e114fe2691eb28cc1680e5fec532d64c80d2f6b737e8b43b94d5a9c73206ac6235c50ff992133e4d38");
|
||||
// nodes.put("localNode2","044e0c127e24407ee8a8abd4fe507b32b340ce9775317b8d7b5bb8e182745d6a45c57aaf867d80a5f816a7561564f9294c6aee5916f95e93c0011e16c28b9e849a");
|
||||
// nodes.put("localNode3","0485040cfd94bec672bb8ba184856188963ee4ad339d247a76e2d9819f20e61bfad24ec763b1371998583f9dc0cf55c4d53cb1a2ec84c67aed1aa5203cc84fc78f");
|
||||
// nodes.put("localNode4","");
|
||||
// nodes.put("localNode5","");
|
||||
//
|
||||
//
|
||||
// //生成崩溃序列
|
||||
// crashSeries.clear();
|
||||
// for(int i = 1;i <= totalRequest;i++){
|
||||
// int temp = i % nodeCount;
|
||||
// if(temp == 0)
|
||||
// temp = nodeCount;
|
||||
// crashSeries.add("crash localNode" + temp);
|
||||
// crashSeries.add("recover localNode" + temp);
|
||||
// }
|
||||
//
|
||||
// System.out.println("崩溃序列" + crashSeries.size());
|
||||
//
|
||||
// Timer timer = new Timer();
|
||||
// tt = new TestTask();
|
||||
// timer.schedule(tt, new Date(), period);
|
||||
// }
|
||||
//
|
||||
// static class TestTask extends TimerTask {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// if(TestADSP.getFlag()){
|
||||
// int index = TestADSP.crashIndex.getAndIncrement();
|
||||
// System.out.println("[TestADSP] index=" + TestADSP.crashIndex.get());
|
||||
//
|
||||
// String[] crash = TestADSP.crashSeries.get(index).split(" ");
|
||||
// String pubKey = convertNameToPubkey(crash[1]);
|
||||
// switch (crash[0]){
|
||||
// case "crash":
|
||||
// if(pubKey != null){
|
||||
// System.out.println("[TestADSP] 令节点 " + crash[1] + "崩溃");
|
||||
// System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())));
|
||||
// crashSet.add(pubKey);
|
||||
// }
|
||||
// break;
|
||||
// case "recover":
|
||||
// if(pubKey != null){
|
||||
// if(crashSet.contains(pubKey)){
|
||||
// crashSet.remove(pubKey);
|
||||
// }
|
||||
// recover.add(pubKey);
|
||||
// System.out.println("[TestADSP] 令节点 " + crash[1] + "上线");
|
||||
// System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())));
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// try {
|
||||
// Thread.sleep(period / 2);
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// System.out.println("[TestADSP]发起请求 " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())));
|
||||
// JsonObject jo = new JsonObject();
|
||||
// jo.addProperty("action", TestADSP.action);
|
||||
// jo.addProperty("contractID", TestADSP.contractID);
|
||||
// jo.addProperty("operation", TestADSP.operation);
|
||||
// jo.addProperty("arg", TestADSP.arg);
|
||||
// jo.addProperty("pubkey",TestADSP.pubkey);
|
||||
// jo.addProperty("signature",TestADSP.signature);
|
||||
// UnitActions.testExecuteContract(jo,null);
|
||||
//
|
||||
// if(index == (TestADSP.crashSeries.size() - 1)){
|
||||
// System.out.println("测试停止!");
|
||||
// TestADSP.setFlag(false);
|
||||
// //TestADSP.check();
|
||||
// }
|
||||
// }//if
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static boolean getFlag(){
|
||||
// boolean temp;
|
||||
// synchronized (flag){
|
||||
// temp = flag;
|
||||
// }
|
||||
// return temp;
|
||||
// }
|
||||
//
|
||||
// public static void setFlag(boolean temp){
|
||||
// synchronized (flag){
|
||||
// flag = temp;
|
||||
// System.out.println("[TestADSP]设置flag为" + flag);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static void getSig(){
|
||||
// String temp = contractID + "|" + operation + "|" + arg + "|" + pubkey;
|
||||
// SM2 sm2 = new SM2();
|
||||
// signature = sm2.sign(temp.getBytes(),priKey).toString();
|
||||
// }
|
||||
//
|
||||
// //查看结果输出文件
|
||||
// public static void check() {
|
||||
// tt.cancel();
|
||||
//
|
||||
// int correct = 0;
|
||||
// int incorrect = 0;
|
||||
// int unavailable = 0;
|
||||
// int fileTotal = 0;
|
||||
//
|
||||
// File file = new File("./front-cluster/testADSP/result.txt");
|
||||
// System.out.println(file.getAbsolutePath());
|
||||
// StringBuilder result = new StringBuilder();
|
||||
// try{
|
||||
// BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));//构造一个BufferedReader类来读取文件
|
||||
//
|
||||
// String s = null;
|
||||
// while((s = br.readLine())!=null){//使用readLine方法,一次读一行
|
||||
// if(!s.equals("")){
|
||||
// fileTotal++;
|
||||
// String str[] = s.split(" ");
|
||||
// if(str[1].equals((Integer.parseInt(str[0]) + 1) + ".0")){
|
||||
// correct++;
|
||||
// }else{
|
||||
// incorrect++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// br.close();
|
||||
//
|
||||
// }catch(Exception e){
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// unavailable = totalRequest * 2 - fileTotal;
|
||||
//
|
||||
// System.out.println("共有" + totalRequest * 2 + "次请求,其中" + correct + "正确," + incorrect + "不正确," + unavailable + "不可用.");
|
||||
// }
|
||||
//
|
||||
// public static String convertNameToPubkey(String nodeName){
|
||||
// return nodes.get(nodeName);
|
||||
// }
|
||||
//
|
||||
// public static String convertPubKeyToName(String pubkey){
|
||||
// for(String key : nodes.keySet()){
|
||||
// if(nodes.get(key).equals(pubkey)){
|
||||
// return key;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public static void main(String[] args){
|
||||
// check();
|
||||
// }
|
||||
}
|
84
src/test/java/org/bdware/bdserver/test/TestSearch.java
Normal file
84
src/test/java/org/bdware/bdserver/test/TestSearch.java
Normal file
@ -0,0 +1,84 @@
|
||||
package org.bdware.bdserver.test;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.bdware.sc.http.HttpUtil;
|
||||
import org.bdware.sc.util.JsonUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class TestSearch {
|
||||
private static final Logger LOGGER = LogManager.getLogger(TestSearch.class);
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String url = "http://127.0.0.1:18005/doip?pubkey=04&owner=0&contractID=0&readmeStr=0";
|
||||
LOGGER.info(JsonUtil.toJson(HttpUtil.httpGet(url)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexSearch() throws Exception {
|
||||
|
||||
//1. 创建分词器(对搜索的关键词进行分词使用)
|
||||
//注意: 分词器要和创建索引的时候使用的分词器一模一样
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
|
||||
//2. 创建查询对象,
|
||||
//第一个参数: 默认查询域, 如果查询的关键字中带搜索的域名, 则从指定域中查询, 如果不带域名则从, 默认搜索域中查询
|
||||
//第二个参数: 使用的分词器
|
||||
QueryParser queryParser = new QueryParser("name", analyzer);
|
||||
|
||||
//3. 设置搜索关键词
|
||||
//华 OR 为 手 机
|
||||
Query query = queryParser.parse("华为手机");
|
||||
|
||||
//4. 创建Directory目录对象, 指定索引库的位置
|
||||
Directory dir = FSDirectory.open(Paths.get("E:\\dir"));
|
||||
//5. 创建输入流对象
|
||||
IndexReader indexReader = DirectoryReader.open(dir);
|
||||
//6. 创建搜索对象
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
//7. 搜索, 并返回结果
|
||||
//第二个参数: 是返回多少条数据用于展示, 分页使用
|
||||
TopDocs topDocs = indexSearcher.search(query, 10);
|
||||
|
||||
//获取查询到的结果集的总数, 打印
|
||||
System.out.println("=======count=======" + topDocs.totalHits);
|
||||
|
||||
//8. 获取结果集
|
||||
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
|
||||
|
||||
//9. 遍历结果集
|
||||
if (scoreDocs != null) {
|
||||
for (ScoreDoc scoreDoc : scoreDocs) {
|
||||
//获取查询到的文档唯一标识, 文档id, 这个id是lucene在创建文档的时候自动分配的
|
||||
int docID = scoreDoc.doc;
|
||||
//通过文档id, 读取文档
|
||||
Document doc = indexSearcher.doc(docID);
|
||||
System.out.println("==================================================");
|
||||
//通过域名, 从文档中获取域值
|
||||
System.out.println("===id==" + doc.get("id"));
|
||||
System.out.println("===name==" + doc.get("name"));
|
||||
System.out.println("===price==" + doc.get("price"));
|
||||
System.out.println("===image==" + doc.get("image"));
|
||||
System.out.println("===brandName==" + doc.get("brandName"));
|
||||
System.out.println("===categoryName==" + doc.get("categoryName"));
|
||||
|
||||
}
|
||||
}
|
||||
//10. 关闭流
|
||||
}
|
||||
}
|
@ -0,0 +1,246 @@
|
||||
package org.bdware.bdserver.testLucene;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.document.*;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.IndexWriterConfig;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class TestManager {
|
||||
|
||||
/**
|
||||
* 创建索引库
|
||||
*/
|
||||
@Test
|
||||
public void createIndexTest() throws Exception {
|
||||
//1. 采集数据
|
||||
SkuDao skuDao = new SkuDaoImpl();
|
||||
List<Sku> skuList = skuDao.querySkuList();
|
||||
|
||||
//文档集合
|
||||
List<Document> docList = new ArrayList<>();
|
||||
|
||||
for (Sku sku : skuList) {
|
||||
//2. 创建文档对象
|
||||
Document document = new Document();
|
||||
|
||||
//创建域对象并且放入文档对象中
|
||||
/**
|
||||
* 是否分词: 否, 因为主键分词后无意义
|
||||
* 是否索引: 是, 如果根据id主键查询, 就必须索引
|
||||
* 是否存储: 是, 因为主键id比较特殊, 可以确定唯一的一条数据, 在业务上一般有重要所用, 所以存储
|
||||
* 存储后, 才可以获取到id具体的内容
|
||||
*/
|
||||
document.add(new StringField("id", sku.getId(), Field.Store.YES));
|
||||
|
||||
/**
|
||||
* 是否分词: 是, 因为名称字段需要查询, 并且分词后有意义所以需要分词
|
||||
* 是否索引: 是, 因为需要根据名称字段查询
|
||||
* 是否存储: 是, 因为页面需要展示商品名称, 所以需要存储
|
||||
*/
|
||||
document.add(new TextField("name", sku.getName(), Field.Store.YES));
|
||||
|
||||
/**
|
||||
* 是否分词: 是(因为lucene底层算法规定, 如果根据价格范围查询, 必须分词)
|
||||
* 是否索引: 是, 需要根据价格进行范围查询, 所以必须索引
|
||||
* 是否存储: 是, 因为页面需要展示价格
|
||||
*/
|
||||
document.add(new IntPoint("price", sku.getPrice()));
|
||||
document.add(new StoredField("price", sku.getPrice()));
|
||||
|
||||
/**
|
||||
* 是否分词: 否, 因为不查询, 所以不索引, 因为不索引所以不分词
|
||||
* 是否索引: 否, 因为不需要根据图片地址路径查询
|
||||
* 是否存储: 是, 因为页面需要展示商品图片
|
||||
*/
|
||||
document.add(new StoredField("image", sku.getImage()));
|
||||
|
||||
/**
|
||||
* 是否分词: 否, 因为分类是专有名词, 是一个整体, 所以不分词
|
||||
* 是否索引: 是, 因为需要根据分类查询
|
||||
* 是否存储: 是, 因为页面需要展示分类
|
||||
*/
|
||||
document.add(new StringField("categoryName", sku.getCategoryName(), Field.Store.YES));
|
||||
|
||||
/**
|
||||
* 是否分词: 否, 因为品牌是专有名词, 是一个整体, 所以不分词
|
||||
* 是否索引: 是, 因为需要根据品牌进行查询
|
||||
* 是否存储: 是, 因为页面需要展示品牌
|
||||
*/
|
||||
document.add(new StringField("brandName", sku.getBrandName(), Field.Store.YES));
|
||||
|
||||
//将文档对象放入到文档集合中
|
||||
docList.add(document);
|
||||
}
|
||||
//3. 创建分词器, StandardAnalyzer标准分词器, 对英文分词效果好, 对中文是单字分词, 也就是一个字就认为是一个词.
|
||||
Analyzer analyzer = new IKAnalyzer();
|
||||
//4. 创建Directory目录对象, 目录对象表示索引库的位置
|
||||
Directory dir = FSDirectory.open(Paths.get("E:\\dir"));
|
||||
//5. 创建IndexWriterConfig对象, 这个对象中指定切分词使用的分词器
|
||||
IndexWriterConfig config = new IndexWriterConfig(analyzer);
|
||||
//6. 创建IndexWriter输出流对象, 指定输出的位置和使用的config初始化对象
|
||||
IndexWriter indexWriter = new IndexWriter(dir, config);
|
||||
//7. 写入文档到索引库
|
||||
for (Document doc : docList) {
|
||||
indexWriter.addDocument(doc);
|
||||
}
|
||||
//8. 释放资源
|
||||
indexWriter.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 索引库修改操作
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void updateIndexTest() throws Exception {
|
||||
//需要变更成的内容
|
||||
Document document = new Document();
|
||||
|
||||
document.add(new StringField("id", "100000003145", Field.Store.YES));
|
||||
document.add(new TextField("name", "xxxx", Field.Store.YES));
|
||||
document.add(new IntPoint("price", 123));
|
||||
document.add(new StoredField("price", 123));
|
||||
document.add(new StoredField("image", "xxxx.jpg"));
|
||||
document.add(new StringField("categoryName", "手机", Field.Store.YES));
|
||||
document.add(new StringField("brandName", "华为", Field.Store.YES));
|
||||
|
||||
|
||||
//3. 创建分词器, StandardAnalyzer标准分词器, 对英文分词效果好, 对中文是单字分词, 也就是一个字就认为是一个词.
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
//4. 创建Directory目录对象, 目录对象表示索引库的位置
|
||||
Directory dir = FSDirectory.open(Paths.get("E:\\dir"));
|
||||
//5. 创建IndexWriterConfig对象, 这个对象中指定切分词使用的分词器
|
||||
IndexWriterConfig config = new IndexWriterConfig(analyzer);
|
||||
//6. 创建IndexWriter输出流对象, 指定输出的位置和使用的config初始化对象
|
||||
IndexWriter indexWriter = new IndexWriter(dir, config);
|
||||
|
||||
|
||||
//修改, 第一个参数: 修改条件, 第二个参数: 修改成的内容
|
||||
indexWriter.updateDocument(new Term("id", "100000003145"), document);
|
||||
|
||||
|
||||
//8. 释放资源
|
||||
indexWriter.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试根据条件删除
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void deleteIndexTest() throws Exception {
|
||||
//3. 创建分词器, StandardAnalyzer标准分词器, 对英文分词效果好, 对中文是单字分词, 也就是一个字就认为是一个词.
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
//4. 创建Directory目录对象, 目录对象表示索引库的位置
|
||||
Directory dir = FSDirectory.open(Paths.get("E:\\dir"));
|
||||
//5. 创建IndexWriterConfig对象, 这个对象中指定切分词使用的分词器
|
||||
IndexWriterConfig config = new IndexWriterConfig(analyzer);
|
||||
//6. 创建IndexWriter输出流对象, 指定输出的位置和使用的config初始化对象
|
||||
IndexWriter indexWriter = new IndexWriter(dir, config);
|
||||
|
||||
|
||||
//测试根据条件删除
|
||||
//indexWriter.deleteDocuments(new Term("id", "100000003145"));
|
||||
|
||||
//测试删除所有内容
|
||||
indexWriter.deleteAll();
|
||||
|
||||
//8. 释放资源
|
||||
indexWriter.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试创建索引速度优化
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void createIndexTest2() throws Exception {
|
||||
//1. 采集数据
|
||||
SkuDao skuDao = new SkuDaoImpl();
|
||||
List<Sku> skuList = skuDao.querySkuList();
|
||||
|
||||
//文档集合
|
||||
List<Document> docList = new ArrayList<>();
|
||||
|
||||
for (Sku sku : skuList) {
|
||||
//2. 创建文档对象
|
||||
Document document = new Document();
|
||||
document.add(new StringField("id", sku.getId(), Field.Store.YES));
|
||||
document.add(new TextField("name", sku.getName(), Field.Store.YES));
|
||||
document.add(new IntPoint("price", sku.getPrice()));
|
||||
document.add(new StoredField("price", sku.getPrice()));
|
||||
document.add(new StoredField("image", sku.getImage()));
|
||||
document.add(new StringField("categoryName", sku.getCategoryName(), Field.Store.YES));
|
||||
document.add(new StringField("brandName", sku.getBrandName(), Field.Store.YES));
|
||||
|
||||
//将文档对象放入到文档集合中
|
||||
docList.add(document);
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
//3. 创建分词器, StandardAnalyzer标准分词器, 对英文分词效果好, 对中文是单字分词, 也就是一个字就认为是一个词.
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
//4. 创建Directory目录对象, 目录对象表示索引库的位置
|
||||
Directory dir = FSDirectory.open(Paths.get("E:\\dir"));
|
||||
//5. 创建IndexWriterConfig对象, 这个对象中指定切分词使用的分词器
|
||||
/**
|
||||
* 没有优化 小100万条数据, 创建索引需要7725ms
|
||||
*
|
||||
*/
|
||||
IndexWriterConfig config = new IndexWriterConfig(analyzer);
|
||||
//设置在内存中多少个文档向磁盘中批量写入一次数据
|
||||
//如果设置的数字过大, 会过多消耗内存, 但是会提升写入磁盘的速度
|
||||
//config.setMaxBufferedDocs(500000);
|
||||
//6. 创建IndexWriter输出流对象, 指定输出的位置和使用的config初始化对象
|
||||
IndexWriter indexWriter = new IndexWriter(dir, config);
|
||||
//设置多少给文档合并成一个段文件,数值越大索引速度越快, 搜索速度越慢; 值越小索引速度越慢, 搜索速度越快
|
||||
//indexWriter.forceMerge(1000000);
|
||||
//7. 写入文档到索引库
|
||||
for (Document doc : docList) {
|
||||
indexWriter.addDocument(doc);
|
||||
}
|
||||
//8. 释放资源
|
||||
indexWriter.close();
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("=====消耗的时间为:==========" + (end - start) + "ms");
|
||||
}
|
||||
|
||||
private String getRmAsString(JsonObject arg) {
|
||||
try {
|
||||
ContractMeta meta =
|
||||
CMActions.manager.statusRecorder.getContractMeta(
|
||||
arg.get("contractID").getAsString());
|
||||
String path = arg.get("assets/README.md").getAsString();
|
||||
ZipFile zipFile = new ZipFile(new File(meta.contract.getScriptStr()));
|
||||
ZipEntry zipEntry = zipFile.getEntry(path);
|
||||
InputStream sc = loadAsInputStream(path);
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
byte[] buff = new byte[1024];
|
||||
for (int k = 0; (k = sc.read(buff)) > 0; ) {
|
||||
bo.write(buff, 0, k);
|
||||
}
|
||||
return new String(bo.toByteArray());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.bdware.bdserver.testLucene;
|
||||
|
||||
import org.bdware.server.nodecenter.MetaIndexAction;
|
||||
import org.junit.Test;
|
||||
|
||||
public class WordSegmentationTest {
|
||||
@Test
|
||||
public void go(){
|
||||
MetaIndexAction i = new MetaIndexAction();
|
||||
i.segmentWord(null,null);
|
||||
}
|
||||
}
|
BIN
temp/CoinUseShading_2021-07-05-22_37_45_Auto.ypk_NC
Normal file
BIN
temp/CoinUseShading_2021-07-05-22_37_45_Auto.ypk_NC
Normal file
Binary file not shown.
BIN
temp/CoinUseShading_2021-07-05-23_29_21_Auto.ypk_NC
Normal file
BIN
temp/CoinUseShading_2021-07-05-23_29_21_Auto.ypk_NC
Normal file
Binary file not shown.
BIN
temp/Counter_2020-12-04-14:39:45_Auto.ypk_NC
Normal file
BIN
temp/Counter_2020-12-04-14:39:45_Auto.ypk_NC
Normal file
Binary file not shown.
BIN
temp/Hello_2021-06-05-21:30:43_Auto.ypk_NC
Normal file
BIN
temp/Hello_2021-06-05-21:30:43_Auto.ypk_NC
Normal file
Binary file not shown.
BIN
temp/Script_749432603.ypk_NC
Normal file
BIN
temp/Script_749432603.ypk_NC
Normal file
Binary file not shown.
BIN
temp/TEMP_2021-06-07-16_28_26_Auto.ypk_NC
Normal file
BIN
temp/TEMP_2021-06-07-16_28_26_Auto.ypk_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593916180187_NC
Normal file
BIN
temp/stateFiles/1593916180187_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593916214495_NC
Normal file
BIN
temp/stateFiles/1593916214495_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593924239336_NC
Normal file
BIN
temp/stateFiles/1593924239336_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593924239381_NC
Normal file
BIN
temp/stateFiles/1593924239381_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593924239413_NC
Normal file
BIN
temp/stateFiles/1593924239413_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593925036315_NC
Normal file
BIN
temp/stateFiles/1593925036315_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593925036321_NC
Normal file
BIN
temp/stateFiles/1593925036321_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593925036323_NC
Normal file
BIN
temp/stateFiles/1593925036323_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593941646859_NC
Normal file
BIN
temp/stateFiles/1593941646859_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593942529107_NC
Normal file
BIN
temp/stateFiles/1593942529107_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593947978273_NC
Normal file
BIN
temp/stateFiles/1593947978273_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593948182712_NC
Normal file
BIN
temp/stateFiles/1593948182712_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593948382831_NC
Normal file
BIN
temp/stateFiles/1593948382831_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593948401893_NC
Normal file
BIN
temp/stateFiles/1593948401893_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593948455304_NC
Normal file
BIN
temp/stateFiles/1593948455304_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593948485794_NC
Normal file
BIN
temp/stateFiles/1593948485794_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593949281596_NC
Normal file
BIN
temp/stateFiles/1593949281596_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593949721642_NC
Normal file
BIN
temp/stateFiles/1593949721642_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593949893442_NC
Normal file
BIN
temp/stateFiles/1593949893442_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593949998893_NC
Normal file
BIN
temp/stateFiles/1593949998893_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593950152800_NC
Normal file
BIN
temp/stateFiles/1593950152800_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593950992421_NC
Normal file
BIN
temp/stateFiles/1593950992421_NC
Normal file
Binary file not shown.
BIN
temp/stateFiles/1593951867738_NC
Normal file
BIN
temp/stateFiles/1593951867738_NC
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user