This commit is contained in:
Hanshuo Zeng
2020-03-04 08:34:08 +08:00
commit 4b772bb3b7
14 changed files with 816 additions and 0 deletions

110
.gitignore vendored Normal file
View File

@@ -0,0 +1,110 @@
# Created by .ignore support plugin (hsz.mobi)
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

28
pom.xml Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hans0924</groupId>
<artifactId>fsd</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<slf4j.version>1.7.30</slf4j.version>
<javolution.version>6.0.0</javolution.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.javolution</groupId>
<artifactId>javolution-core-java</artifactId>
<version>${javolution.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,47 @@
package com.hans0924.fsd;
import com.hans0924.fsd.manager.Manage;
import com.hans0924.fsd.process.PMan;
import com.hans0924.fsd.process.config.ConfigManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class Fsd {
private final static Logger LOGGER = LoggerFactory.getLogger(Fsd.class);
public static ConfigManager configManager;
private int clientPort;
private int serverPort;
private int systemPort;
private PMan pManager;
private String certFile;
private String whazzupFile;
private int timer;
private int prevNotify;
private int prevLagCheck;
private int certFileStat;
private int prevCertCheck;
public Fsd(String configFile) {
LOGGER.info("Booting Server");
pManager = new PMan();
/* Start the information manager */
Manage.manager = new Manage();
configManager = new ConfigManager(configFile);
pManager.registerProcess(configManager);
}
}

View File

@@ -0,0 +1,11 @@
package com.hans0924.fsd;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class FsdLauncher {
public static void main(String[] args) {
}
}

View File

@@ -0,0 +1,13 @@
package com.hans0924.fsd.constants;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public final class ManageVarType {
public static final int ATT_INT = 1;
public static final int ATT_VARCHAR = 5;
public static final int ATT_DATE = 6;
}

View File

@@ -0,0 +1,111 @@
package com.hans0924.fsd.manager;
import com.hans0924.fsd.constants.ManageVarType;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class Manage {
public static Manage manager;
private int nVars;
private List<ManageVar> variables;
public Manage() {
nVars = 0;
variables = new ArrayList<ManageVar>();
}
public int addVar(String name, int type) {
ManageVar var = new ManageVar();
var.setType(type);
var.setName(name);
variables.add(var);
return variables.size();
}
public void delVar(int num) {
if (variables.size() > num) {
variables.remove(num);
}
}
public void incVar(int num) {
ManageVar var = variables.get(num);
ManageVarValue value = var.getValue();
value.setNumber(value.getNumber() + 1);
}
public void decVar(int num) {
ManageVar var = variables.get(num);
ManageVarValue value = var.getValue();
value.setNumber(value.getNumber() - 1);
}
public void setVar(int num, int number) {
ManageVar var = variables.get(num);
ManageVarValue value = var.getValue();
value.setNumber(number);
}
public void setVar(int num, String str) {
ManageVar var = variables.get(num);
ManageVarValue value = var.getValue();
value.setString(str);
}
public void setVar(int num, long timeVal) {
ManageVar var = variables.get(num);
ManageVarValue value = var.getValue();
value.setTimeVal(timeVal);
}
public ManageVarValue getVar(int num) {
if (num >= nVars) {
return null;
}
ManageVar var = variables.get(num);
return var.getValue();
}
public int getNVars() {
return nVars;
}
public String sprintValue(int num) {
if (num >= nVars || variables.get(num).getName() == null) {
return null;
}
ManageVar var = variables.get(num);
switch (var.getType()) {
case ManageVarType
.ATT_INT:
return String.valueOf(var.getValue().getNumber());
case ManageVarType.ATT_VARCHAR:
return var.getValue().getString();
case ManageVarType.ATT_DATE:
return new Date(var.getValue().getTimeVal()).toString();
}
return "";
}
public int getVarNum(String name) {
for (int i = 0; i < variables.size(); i++) {
ManageVar variable = variables.get(i);
if (Objects.equals(variable.getName(), name)) {
return i;
}
}
return -1;
}
}

View File

@@ -0,0 +1,40 @@
package com.hans0924.fsd.manager;
import javolution.io.Struct;
import javolution.io.Union;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class ManageVar {
private int type;
private String name;
private ManageVarValue value;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ManageVarValue getValue() {
return value;
}
public void setValue(ManageVarValue value) {
this.value = value;
}
}

View File

@@ -0,0 +1,37 @@
package com.hans0924.fsd.manager;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class ManageVarValue {
private int number;
private String string;
private long timeVal;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
public long getTimeVal() {
return timeVal;
}
public void setTimeVal(long timeVal) {
this.timeVal = timeVal;
}
}

View File

@@ -0,0 +1,42 @@
package com.hans0924.fsd.process;
import java.io.IOException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Set;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class PMan {
private boolean busy;
private Selector selector;
public PMan() throws IOException {
selector = Selector.open();
busy = false;
}
public void registerProcess(Process process) throws IOException {
process.getChannel().configureBlocking(false);
SelectionKey selectionKey = process.getChannel().register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, process);
process.setSelectionKey(selectionKey);
}
public void run() throws IOException {
long timeOut = busy ? 0 : 1000L;
busy = false;
if (selector.select(timeOut) > 0) {
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey selectionKey : selectionKeys) {
Process attachment = (Process) selectionKey.attachment();
if (attachment.run()) {
busy = true;
}
}
}
}
}

View File

@@ -0,0 +1,40 @@
package com.hans0924.fsd.process;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public abstract class Process {
private SelectableChannel channel;
private SelectionKey selectionKey;
public Process() {
}
public int calcMask() {
return 0;
}
public abstract boolean run();
public SelectableChannel getChannel() {
return channel;
}
public void setChannel(SelectableChannel channel) {
this.channel = channel;
}
public SelectionKey getSelectionKey() {
return selectionKey;
}
public void setSelectionKey(SelectionKey selectionKey) {
this.selectionKey = selectionKey;
}
}

View File

@@ -0,0 +1,89 @@
package com.hans0924.fsd.process.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class ConfigEntry {
private String var;
private String data;
private List<String> parts;
private boolean changed;
private int nParts;
public ConfigEntry(String var, String data) {
this.var = var;
this.data = data;
changed = true;
parts = new ArrayList<>();
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getInt() {
return Integer.parseInt(data);
}
public void fillParts() {
String[] split = data.split(",");
for (String part : split) {
parts.add(part.strip());
}
nParts = split.length;
}
public boolean inList(String entry) {
if (parts.isEmpty()) {
fillParts();
}
for (String part : parts) {
if (Objects.equals(part, entry)) {
return true;
}
}
return false;
}
public int getNParts() {
if (parts.isEmpty()) {
fillParts();
}
return nParts;
}
public String getPart(int num) {
if (parts.isEmpty()) {
fillParts();
}
if (num >= nParts) {
return null;
}
return parts.get(num);
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
}

View File

@@ -0,0 +1,71 @@
package com.hans0924.fsd.process.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author 曾韩铄
* @since 2020-03-04
*/
public class ConfigGroup {
private String name;
private List<ConfigEntry> entries;
private int nEntries;
private boolean changed;
public ConfigGroup(String name) {
this.name = name;
entries = new ArrayList<>();
nEntries = 0;
changed = true;
}
public ConfigEntry getEntry(String name) {
for (ConfigEntry entry : entries) {
if (Objects.equals(entry.getVar(), name)) {
return entry;
}
}
return null;
}
public ConfigEntry createEntry(String var, String data) {
ConfigEntry configEntry = new ConfigEntry(var, data);
entries.add(configEntry);
return configEntry;
}
public void handleEntry(String var, String data) {
ConfigEntry entry = getEntry(var);
if (entry == null) {
createEntry(var, data);
changed = true;
return;
}
if (Objects.equals(entry.getData(), data)) {
return;
}
entry.setData(data);
changed = true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isChanged() {
return changed;
}
}

View File

@@ -0,0 +1,138 @@
package com.hans0924.fsd.process.config;
import com.hans0924.fsd.constants.ManageVarType;
import com.hans0924.fsd.manager.Manage;
import com.hans0924.fsd.process.Process;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author 曾韩铄
* @since 2020-03-03
*/
public class ConfigManager extends Process {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigManager.class);
private static final long CONFIG_INTERVAL = 10_000L;
private String fileName;
private List<ConfigGroup> groups;
private int nGroups;
private int varAccess;
private boolean changed;
private long prevCheck;
private long lastModify;
public ConfigManager(String name) {
super();
fileName = name;
groups = new ArrayList<>();
nGroups = 0;
changed = true;
int fname = Manage.manager.addVar("config.filename", ManageVarType.ATT_VARCHAR);
Manage.manager.setVar(fname, name);
varAccess = Manage.manager.addVar("config.lastread", ManageVarType.ATT_DATE);
parseFile();
}
public ConfigGroup getGroup(String name) {
for (ConfigGroup group : groups) {
if (Objects.equals(group.getName(), name)) {
return group;
}
}
return null;
}
public ConfigGroup createGroup(String name) {
ConfigGroup group = new ConfigGroup(name);
groups.add(group);
return group;
}
@Override
public boolean run() {
long now = System.currentTimeMillis();
if (now - prevCheck < CONFIG_INTERVAL) {
return false;
}
prevCheck = now;
Path file = Path.of(fileName);
if (Files.notExists(file)) {
return false;
}
try {
BasicFileAttributes attr = Files.readAttributes(file, BasicFileAttributes.class);
long fileLastModified = attr.lastModifiedTime().toMillis();
if (fileLastModified == lastModify) {
return false;
}
lastModify = fileLastModified;
parseFile();
return true;
} catch (IOException e) {
return false;
}
}
public void parseFile() {
File file = new File(fileName);
if (!file.isFile() || !file.exists()) {
return;
}
Manage.manager.setVar(varAccess, System.currentTimeMillis());
ConfigGroup current = null;
try (InputStreamReader read = new InputStreamReader(new FileInputStream(file));
BufferedReader bufferedReader = new BufferedReader(read)) {
String line;
while ((line = bufferedReader.readLine()) != null)
{
if (line.charAt(0) == '#' || line.charAt(0) == '\r' || line.charAt(0) == '\n') {
continue;
}
if (line.charAt(0) == '[') {
String entry = line.substring(1, line.length() - 1);
current = getGroup(entry);
if (current == null) {
current = createGroup(entry);
}
continue;
}
if (current == null) {
continue;
}
String[] split = line.split("=");
if (split.length > 1) {
current.handleEntry(split[0], split[1]);
}
if (current.isChanged()) {
changed = true;
}
}
} catch (FileNotFoundException e) {
LOGGER.error("Config file not found: " + fileName);
} catch (IOException e) {
LOGGER.error("Something went wrong when parse config file: ", e);
}
prevCheck = System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,39 @@
#日志级别大小: DEBUG < INFO < WARN < ERROR < FATAL
#log4j.rootLogger 配置的是大于等于当前级别的日志信息的输出
#log4j.rootLogger 用法:注意appenderName可以是一个或多个
#log4j.rootLogger = 日志级别,appenderName1,appenderName2,....
#log4j.appender.appenderName1定义的是日志的输出方式有两种一种是命令行输出或者叫控制台输出另一种是文件方式保存
# 1控制台输出则应该配置为org.apache.log4j.PatternLayout
# 2文本方式保存应该配置为org.apache.log4j.DailyRollingFileAppender
# 3也可以自定义 Appender类
#log4j.appender.appenderName1.layout.ConversionPattern 定义的是日志内容格式
#log4j.appender.appenderName1.file 定义了该日志文件的文件名称
#log4j.appender.appenderName1.DatePattern 定义了日志文件重新生成的时间间隔,如果设置到天,则每天重新生成一个新的日志文件。
# 旧的日志文件则以新的文件名保存,文件名称 = log4j.appender.appenderName1.file + log4j.appender.appenderName1.DatePattern
#log4j.rootLogger = info,stdout,file
log4j.rootLogger = info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%C{1}:%L] - %m%n
#log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.file=d\:\\log\\info(+).log
#log4j.appender.file.DatePattern= '.'yyyy-MM-dd
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%C{1}:%L] - %m%n
# log4j.logger 用法如下
# 1log4j.logger.包名 = 日志级别 , appenderName1,appenderName2,....
# 定义该包名下的所有类的日志输出
# 2log4j.logger.类全名含包名 = 日志级别 , appenderName1,appenderName2,....
# 定义指定类的日志输出
# 3) log4j.logger.日志对象Logger命名名称 = 日志级别 , appenderName1,appenderName2,....
# 定义了某命名名称的日志的 输出,如:
# log4j.logger.Log1 就是指定义通过 Logger.getLogger("Log1") 获取的日志对象的日志输出
log4j.logger.edu.mvcdemo.controller = debug,controller_logfile
log4j.appender.controller_logfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.controller_logfile.file= fsd.log
log4j.appender.controller_logfile.DatePattern= '.'yyyy-MM-dd
log4j.appender.controller_logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.controller_logfile.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%C{1}:%L] - %m%n