Skip to content

Commit 8e68338

Browse files
committedJan 24, 2018
Initial commit
0 parents  commit 8e68338

36 files changed

+1886
-0
lines changed
 

‎.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# eclipse
2+
bin
3+
*.launch
4+
.settings
5+
.metadata
6+
.classpath
7+
.project
8+
9+
# idea
10+
out
11+
*.ipr
12+
*.iws
13+
*.iml
14+
.idea
15+
16+
# gradle
17+
build
18+
.gradle
19+
20+
# other
21+
eclipse
22+
run
23+
24+
*.bytelog*

‎README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Fast Log Block
2+
## Event multithread handling
3+
![](https://image.ibb.co/hyaPRw/Fast_Log_Block.png)
4+
5+
## Log file format
6+
7+
| Name | posX | posY | posZ | typeaction | playerid | blockid | timestamp |
8+
|:--------------------:|:------:|:------:|:------:|:--------------------------------------------------------------------------:|:--------:|:-------:|:---------:|
9+
| Field Length (bytes) | 4 byte | 4 byte | 4 byte | 1 byte ('0' for Remove, '1' for Insert, '2' for update, '100' for unknown) | 4 byte | 8 byte | 8 byte |
10+
11+
Total: 33 bytes per line
12+
13+
Filename: /{save}/{world/dimension}/*.bytelog
14+
15+
| Name | id | blockname |
16+
|:--------------------:|:------:|:------------------:|
17+
| Field Length (bytes) | 8 byte | 1 byte per symbols |
18+
19+
Total: ~ 21 bytes per block
20+
21+
Filename: blockmap.bytelog
22+
23+
| Name | id | nickname |
24+
|:--------------------:|:------:|:------------------:|
25+
| Field Length (bytes) | 4 byte | 1 byte per symbols |
26+
27+
Total: ~ 10 bytes per Player
28+
29+
Filename: nickmap.bytelog
30+

‎build.gradle

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
buildscript {
2+
repositories {
3+
jcenter()
4+
maven { url = "http://files.minecraftforge.net/maven" }
5+
}
6+
dependencies {
7+
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
8+
}
9+
}
10+
apply plugin: 'java'
11+
apply plugin: 'net.minecraftforge.gradle.forge'
12+
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
13+
14+
15+
version = "1.0"
16+
group = "ru.lionzxy.fastlogblock" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
17+
archivesBaseName = "FastLogBlock"
18+
19+
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
20+
compileJava {
21+
sourceCompatibility = targetCompatibility = '1.8'
22+
}
23+
24+
minecraft {
25+
version = "1.12.2-14.23.1.2555"
26+
runDir = "run"
27+
28+
// the mappings can be changed at any time, and must be in the following format.
29+
// snapshot_YYYYMMDD snapshot are built nightly.
30+
// stable_# stables are built at the discretion of the MCP team.
31+
// Use non-default mappings at your own risk. they may not always work.
32+
// simply re-run your setup task after changing the mappings to update your workspace.
33+
mappings = "snapshot_20171003"
34+
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
35+
}
36+
37+
dependencies {
38+
// you may put jars on which you depend on in ./libs
39+
// or you may define them like so..
40+
//compile "some.group:artifact:version:classifier"
41+
//compile "some.group:artifact:version"
42+
// https://mvnrepository.com/artifact/trove/trove
43+
compile "trove:trove:1.0.2"
44+
45+
// https://mvnrepository.com/artifact/org.mapdb/thread-weaver
46+
testCompile 'junit:junit:4.12'
47+
testCompile "org.mapdb:thread-weaver:3.0.mapdb"
48+
49+
// real examples
50+
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
51+
//compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
52+
53+
// the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
54+
//provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
55+
56+
// the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
57+
// except that these dependencies get remapped to your current MCP mappings
58+
//deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
59+
//deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
60+
61+
// for more info...
62+
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
63+
// http://www.gradle.org/docs/current/userguide/dependency_management.html
64+
65+
}
66+
67+
processResources {
68+
// this will ensure that this task is redone when the versions change.
69+
inputs.property "version", project.version
70+
inputs.property "mcversion", project.minecraft.version
71+
72+
// replace stuff in mcmod.info, nothing else
73+
from(sourceSets.main.resources.srcDirs) {
74+
include 'mcmod.info'
75+
76+
// replace version and mcversion
77+
expand 'version': project.version, 'mcversion': project.minecraft.version
78+
}
79+
80+
// copy everything else except the mcmod.info
81+
from(sourceSets.main.resources.srcDirs) {
82+
exclude 'mcmod.info'
83+
}
84+
}

‎gradle.properties

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
2+
# This is required to provide enough memory for the Minecraft decompilation process.
3+
org.gradle.jvmargs=-Xmx3G

‎gradle/wrapper/gradle-wrapper.jar

52.1 KB
Binary file not shown.
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#Sun Jan 21 21:37:17 MSK 2018
2+
distributionBase=GRADLE_USER_HOME
3+
distributionPath=wrapper/dists
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

‎gradlew

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#!/usr/bin/env bash
2+
3+
##############################################################################
4+
##
5+
## Gradle start up script for UN*X
6+
##
7+
##############################################################################
8+
9+
# Attempt to set APP_HOME
10+
# Resolve links: $0 may be a link
11+
PRG="$0"
12+
# Need this for relative symlinks.
13+
while [ -h "$PRG" ] ; do
14+
ls=`ls -ld "$PRG"`
15+
link=`expr "$ls" : '.*-> \(.*\)$'`
16+
if expr "$link" : '/.*' > /dev/null; then
17+
PRG="$link"
18+
else
19+
PRG=`dirname "$PRG"`"/$link"
20+
fi
21+
done
22+
SAVED="`pwd`"
23+
cd "`dirname \"$PRG\"`/" >/dev/null
24+
APP_HOME="`pwd -P`"
25+
cd "$SAVED" >/dev/null
26+
27+
APP_NAME="Gradle"
28+
APP_BASE_NAME=`basename "$0"`
29+
30+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31+
DEFAULT_JVM_OPTS=""
32+
33+
# Use the maximum available, or set MAX_FD != -1 to use that value.
34+
MAX_FD="maximum"
35+
36+
warn ( ) {
37+
echo "$*"
38+
}
39+
40+
die ( ) {
41+
echo
42+
echo "$*"
43+
echo
44+
exit 1
45+
}
46+
47+
# OS specific support (must be 'true' or 'false').
48+
cygwin=false
49+
msys=false
50+
darwin=false
51+
nonstop=false
52+
case "`uname`" in
53+
CYGWIN* )
54+
cygwin=true
55+
;;
56+
Darwin* )
57+
darwin=true
58+
;;
59+
MINGW* )
60+
msys=true
61+
;;
62+
NONSTOP* )
63+
nonstop=true
64+
;;
65+
esac
66+
67+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68+
69+
# Determine the Java command to use to start the JVM.
70+
if [ -n "$JAVA_HOME" ] ; then
71+
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72+
# IBM's JDK on AIX uses strange locations for the executables
73+
JAVACMD="$JAVA_HOME/jre/sh/java"
74+
else
75+
JAVACMD="$JAVA_HOME/bin/java"
76+
fi
77+
if [ ! -x "$JAVACMD" ] ; then
78+
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79+
80+
Please set the JAVA_HOME variable in your environment to match the
81+
location of your Java installation."
82+
fi
83+
else
84+
JAVACMD="java"
85+
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86+
87+
Please set the JAVA_HOME variable in your environment to match the
88+
location of your Java installation."
89+
fi
90+
91+
# Increase the maximum file descriptors if we can.
92+
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93+
MAX_FD_LIMIT=`ulimit -H -n`
94+
if [ $? -eq 0 ] ; then
95+
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96+
MAX_FD="$MAX_FD_LIMIT"
97+
fi
98+
ulimit -n $MAX_FD
99+
if [ $? -ne 0 ] ; then
100+
warn "Could not set maximum file descriptor limit: $MAX_FD"
101+
fi
102+
else
103+
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104+
fi
105+
fi
106+
107+
# For Darwin, add options to specify how the application appears in the dock
108+
if $darwin; then
109+
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110+
fi
111+
112+
# For Cygwin, switch paths to Windows format before running java
113+
if $cygwin ; then
114+
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115+
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116+
JAVACMD=`cygpath --unix "$JAVACMD"`
117+
118+
# We build the pattern for arguments to be converted via cygpath
119+
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120+
SEP=""
121+
for dir in $ROOTDIRSRAW ; do
122+
ROOTDIRS="$ROOTDIRS$SEP$dir"
123+
SEP="|"
124+
done
125+
OURCYGPATTERN="(^($ROOTDIRS))"
126+
# Add a user-defined pattern to the cygpath arguments
127+
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128+
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129+
fi
130+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
131+
i=0
132+
for arg in "$@" ; do
133+
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134+
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135+
136+
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137+
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138+
else
139+
eval `echo args$i`="\"$arg\""
140+
fi
141+
i=$((i+1))
142+
done
143+
case $i in
144+
(0) set -- ;;
145+
(1) set -- "$args0" ;;
146+
(2) set -- "$args0" "$args1" ;;
147+
(3) set -- "$args0" "$args1" "$args2" ;;
148+
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149+
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150+
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151+
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152+
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153+
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154+
esac
155+
fi
156+
157+
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158+
function splitJvmOpts() {
159+
JVM_OPTS=("$@")
160+
}
161+
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162+
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163+
164+
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

‎gradlew.bat

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
@if "%DEBUG%" == "" @echo off
2+
@rem ##########################################################################
3+
@rem
4+
@rem Gradle startup script for Windows
5+
@rem
6+
@rem ##########################################################################
7+
8+
@rem Set local scope for the variables with windows NT shell
9+
if "%OS%"=="Windows_NT" setlocal
10+
11+
set DIRNAME=%~dp0
12+
if "%DIRNAME%" == "" set DIRNAME=.
13+
set APP_BASE_NAME=%~n0
14+
set APP_HOME=%DIRNAME%
15+
16+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17+
set DEFAULT_JVM_OPTS=
18+
19+
@rem Find java.exe
20+
if defined JAVA_HOME goto findJavaFromJavaHome
21+
22+
set JAVA_EXE=java.exe
23+
%JAVA_EXE% -version >NUL 2>&1
24+
if "%ERRORLEVEL%" == "0" goto init
25+
26+
echo.
27+
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28+
echo.
29+
echo Please set the JAVA_HOME variable in your environment to match the
30+
echo location of your Java installation.
31+
32+
goto fail
33+
34+
:findJavaFromJavaHome
35+
set JAVA_HOME=%JAVA_HOME:"=%
36+
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37+
38+
if exist "%JAVA_EXE%" goto init
39+
40+
echo.
41+
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42+
echo.
43+
echo Please set the JAVA_HOME variable in your environment to match the
44+
echo location of your Java installation.
45+
46+
goto fail
47+
48+
:init
49+
@rem Get command-line arguments, handling Windows variants
50+
51+
if not "%OS%" == "Windows_NT" goto win9xME_args
52+
if "%@eval[2+2]" == "4" goto 4NT_args
53+
54+
:win9xME_args
55+
@rem Slurp the command line arguments.
56+
set CMD_LINE_ARGS=
57+
set _SKIP=2
58+
59+
:win9xME_args_slurp
60+
if "x%~1" == "x" goto execute
61+
62+
set CMD_LINE_ARGS=%*
63+
goto execute
64+
65+
:4NT_args
66+
@rem Get arguments from the 4NT Shell from JP Software
67+
set CMD_LINE_ARGS=%$
68+
69+
:execute
70+
@rem Setup the command line
71+
72+
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73+
74+
@rem Execute Gradle
75+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76+
77+
:end
78+
@rem End local scope for the variables with windows NT shell
79+
if "%ERRORLEVEL%"=="0" goto mainEnd
80+
81+
:fail
82+
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83+
rem the _cmd.exe /c_ return code!
84+
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85+
exit /b 1
86+
87+
:mainEnd
88+
if "%OS%"=="Windows_NT" endlocal
89+
90+
:omega
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package ru.lionzxy.fastlogblock;
2+
3+
import net.minecraftforge.common.MinecraftForge;
4+
import net.minecraftforge.event.world.BlockEvent;
5+
import net.minecraftforge.fml.common.FMLLog;
6+
import net.minecraftforge.fml.common.Mod;
7+
import net.minecraftforge.fml.common.Mod.EventHandler;
8+
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
9+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
10+
import ru.lionzxy.fastlogblock.config.LogConfig;
11+
import ru.lionzxy.fastlogblock.io.WriteRunnable;
12+
import ru.lionzxy.fastlogblock.models.BlockChangeEventModel;
13+
14+
import java.io.File;
15+
import java.io.IOException;
16+
17+
@Mod(modid = FastLogBlock.MODID, version = FastLogBlock.VERSION)
18+
public class FastLogBlock {
19+
@Mod.Instance
20+
public static FastLogBlock fastLogBlock;
21+
public static final File rootMinecraftPath = new File("./");
22+
public File logFolderFile;
23+
public static final String MODID = "fastlogblock";
24+
public static final String VERSION = "1.0";
25+
26+
@EventHandler
27+
public void init(final FMLInitializationEvent event) throws IOException {
28+
logFolderFile = new File(rootMinecraftPath, LogConfig.logFolderPath);
29+
FMLLog.log.info("FullPath: " + logFolderFile.getAbsolutePath());
30+
final WriteRunnable writeRunnable = new WriteRunnable();
31+
MinecraftForge.EVENT_BUS.register(this);
32+
}
33+
34+
@SubscribeEvent
35+
public void onBlockBreak(final BlockEvent.BreakEvent event) {
36+
final BlockChangeEventModel blockChangeEventModel = BlockChangeEventModel.getChangeEvent(event);
37+
38+
if (blockChangeEventModel == null) {
39+
return;
40+
}
41+
42+
FMLLog.log.info(blockChangeEventModel.toString());
43+
}
44+
45+
@SubscribeEvent
46+
public void onBlockPlace(final BlockEvent.PlaceEvent event) {
47+
final BlockChangeEventModel blockChangeEventModel = BlockChangeEventModel.getChangeEvent(event);
48+
49+
if (blockChangeEventModel == null) {
50+
return;
51+
}
52+
53+
FMLLog.log.info(blockChangeEventModel.toString());
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package ru.lionzxy.fastlogblock.config;
2+
3+
4+
import net.minecraftforge.common.config.Config;
5+
import net.minecraftforge.common.config.ConfigManager;
6+
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
7+
import net.minecraftforge.fml.common.Mod;
8+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
9+
import ru.lionzxy.fastlogblock.FastLogBlock;
10+
import ru.lionzxy.fastlogblock.io.filesplitter.FileSplitterEnum;
11+
12+
@Config(modid = FastLogBlock.MODID)
13+
@Config.LangKey("fastlogblock.config.title")
14+
public class LogConfig {
15+
@Config.Comment("Filepath from minecraft root folder to block log path")
16+
public static final String logFolderPath = "./blocklog/";
17+
18+
@Config.Comment("File splitter type. SINGLE for single-file strategy, BLOCKHASH for file=HASH(BlockPos) strategy")
19+
public static FileSplitterEnum fileSplitterType = FileSplitterEnum.BLOCKHASH;
20+
21+
@Config.Comment("Utils information for migration")
22+
public static int logSchemeVersion = 1;
23+
24+
@Config.Comment("Path to mapper file from logFolderPath")
25+
public static final String nickToIntFilePath = "nicktoid.prop";
26+
27+
@Config.Comment("Path to mapper file from logFolderPath")
28+
public static String blockToIntFilePath = "blocktoid.prop";
29+
30+
@Config.Comment("Regular expression for block change event ignore")
31+
public static String[] ignoreBlockNamesRegExp = new String[]{"<minecraft:tallgrass:*>"};
32+
33+
public static final HashConfig HASH_CONFIG = new HashConfig();
34+
35+
public static class HashConfig {
36+
@Config.Comment("Max logfile count")
37+
public final int fileCount = 16;
38+
39+
@Config.Comment("Pattern for log filename. %d - file number. Default: part%d.bytelog")
40+
public final String fileNamePattern = "part%d.bytelog";
41+
}
42+
43+
@Mod.EventBusSubscriber(modid = FastLogBlock.MODID)
44+
private static class EventHandler {
45+
46+
/**
47+
* Inject the new values and save to the config file when the config has been changed from the GUI.
48+
*
49+
* @param event The event
50+
*/
51+
@SubscribeEvent
52+
public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event) {
53+
if (event.getModID().equals(FastLogBlock.MODID)) {
54+
ConfigManager.sync(FastLogBlock.MODID, Config.Type.INSTANCE);
55+
}
56+
}
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import ru.lionzxy.fastlogblock.FastLogBlock;
4+
import ru.lionzxy.fastlogblock.config.LogConfig;
5+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
10+
public class WriteRunnable implements Runnable {
11+
12+
public WriteRunnable() throws IOException {
13+
NickMapper nickMapper = new NickMapper(new File(FastLogBlock.fastLogBlock.logFolderFile,
14+
LogConfig.nickToIntFilePath));
15+
//nickMapper.putNewUser(new ASCIString("LionZXY"));
16+
nickMapper.sync();
17+
}
18+
19+
@Override
20+
public void run() {
21+
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package ru.lionzxy.fastlogblock.io.base;
2+
3+
import gnu.trove.list.array.TByteArrayList;
4+
import net.minecraftforge.fml.common.FMLLog;
5+
import ru.lionzxy.fastlogblock.utils.FileUtils;
6+
7+
import java.io.*;
8+
import java.nio.file.Files;
9+
import java.nio.file.StandardCopyOption;
10+
import java.util.concurrent.atomic.AtomicBoolean;
11+
import java.util.concurrent.locks.ReentrantReadWriteLock;
12+
import java.util.function.Consumer;
13+
14+
public abstract class IterrateByteFile {
15+
protected final File file;
16+
protected final AtomicBoolean markDirty = new AtomicBoolean(false);
17+
protected final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
18+
19+
public IterrateByteFile(final File file) {
20+
this.file = file;
21+
}
22+
23+
public void iterateByFile(final Consumer<TByteArrayList> callback) throws IOException {
24+
FileUtils.createFileIfNotExist(file);
25+
26+
try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) {
27+
readWriteLock.writeLock().lock();
28+
try {
29+
iterateByByte(bufferedInputStream, callback);
30+
} finally {
31+
readWriteLock.writeLock().unlock();
32+
}
33+
}
34+
}
35+
36+
private void iterateByByte(final InputStream is, final Consumer<TByteArrayList> callback) throws IOException {
37+
final byte[] buffer = new byte[FileUtils.BYTEBUFFERSIZE];
38+
int len;
39+
40+
final TByteArrayList arrayList = new TByteArrayList();
41+
while ((len = is.read(buffer)) != -1) {
42+
for (int i = 0; i < len; i++) {
43+
arrayList.add(buffer[i]);
44+
45+
if (checkLineEnd(arrayList, buffer[i])) {
46+
callback.accept(arrayList);
47+
arrayList.clear(arrayList.size());
48+
}
49+
}
50+
}
51+
}
52+
53+
public void sync() throws IOException {
54+
if (markDirty.compareAndSet(false, false)) {
55+
return;
56+
}
57+
58+
FMLLog.log.debug("Sync nickToId map...");
59+
60+
Files.move(file.toPath(), new File(file.getParent(), file.getName() + ".backup").toPath(),
61+
StandardCopyOption.REPLACE_EXISTING);
62+
63+
FileUtils.createFileIfNotExist(file);
64+
65+
try (final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file))) {
66+
readWriteLock.readLock().lock();
67+
try {
68+
writeToFile(bufferedOutputStream);
69+
} finally {
70+
readWriteLock.readLock().lock();
71+
}
72+
}
73+
74+
FMLLog.log.debug("Sync finished!");
75+
}
76+
77+
protected abstract boolean checkLineEnd(TByteArrayList arrayList, byte endByte);
78+
79+
protected abstract void writeToFile(OutputStream outputStream) throws IOException;
80+
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ru.lionzxy.fastlogblock.io.filesplitter;
2+
3+
import ru.lionzxy.fastlogblock.FastLogBlock;
4+
import ru.lionzxy.fastlogblock.io.filesplitter.impl.BlockHashFileSplitter;
5+
import ru.lionzxy.fastlogblock.io.filesplitter.impl.SingleFileSplitter;
6+
7+
public enum FileSplitterEnum {
8+
SINGLE(new SingleFileSplitter(FastLogBlock.rootMinecraftPath)),
9+
BLOCKHASH(new BlockHashFileSplitter(FastLogBlock.rootMinecraftPath));
10+
11+
private final IFileSplitter fileSplitter;
12+
13+
FileSplitterEnum(final IFileSplitter fileSplitter) {
14+
this.fileSplitter = fileSplitter;
15+
}
16+
17+
public IFileSplitter getFileSplitter() {
18+
return fileSplitter;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package ru.lionzxy.fastlogblock.io.filesplitter;
2+
3+
public class FileSplitterManager {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package ru.lionzxy.fastlogblock.io.filesplitter;
2+
3+
import net.minecraft.util.math.BlockPos;
4+
5+
import java.io.File;
6+
7+
public abstract class IFileSplitter {
8+
protected final File modFolder;
9+
10+
public IFileSplitter(final File modFolder) {
11+
this.modFolder = modFolder;
12+
}
13+
14+
public abstract File[] getAllLogFile();
15+
16+
public abstract File getFileByPos(BlockPos blockPos);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package ru.lionzxy.fastlogblock.io.filesplitter.impl;
2+
3+
import net.minecraft.util.math.BlockPos;
4+
import ru.lionzxy.fastlogblock.config.LogConfig;
5+
import ru.lionzxy.fastlogblock.io.filesplitter.IFileSplitter;
6+
7+
import java.io.File;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
public class BlockHashFileSplitter extends IFileSplitter {
12+
private static final int MAGIC_HASH_NUMBER = 31;
13+
14+
public BlockHashFileSplitter(final File modFolder) {
15+
super(modFolder);
16+
}
17+
18+
@Override
19+
public File[] getAllLogFile() {
20+
final List<File> fileList = new ArrayList<>(LogConfig.HASH_CONFIG.fileCount);
21+
for (int i = 0; i < LogConfig.HASH_CONFIG.fileCount; i++) {
22+
fileList.add(new File(this.modFolder,
23+
String.format(LogConfig.HASH_CONFIG.fileNamePattern, i)
24+
));
25+
}
26+
return fileList.toArray(new File[fileList.size()]);
27+
}
28+
29+
@Override
30+
public File getFileByPos(final BlockPos blockPos) {
31+
return new File(String.format(LogConfig.HASH_CONFIG.fileNamePattern, hashByBlock(blockPos)));
32+
}
33+
34+
private static int hashByBlock(final BlockPos blockPos) {
35+
final int signedHash = ((blockPos.getX() * MAGIC_HASH_NUMBER +
36+
blockPos.getY()) * MAGIC_HASH_NUMBER +
37+
blockPos.getZ()) * MAGIC_HASH_NUMBER;
38+
final int hash = Math.abs(signedHash) % LogConfig.HASH_CONFIG.fileCount;
39+
return hash < 0 ? 0 : hash;
40+
}
41+
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ru.lionzxy.fastlogblock.io.filesplitter.impl;
2+
3+
import net.minecraft.util.math.BlockPos;
4+
import ru.lionzxy.fastlogblock.io.filesplitter.IFileSplitter;
5+
6+
import java.io.File;
7+
8+
public class SingleFileSplitter extends IFileSplitter {
9+
private final File logFile;
10+
11+
public SingleFileSplitter(final File modFolder) {
12+
super(modFolder);
13+
logFile = new File(modFolder, "block.bytelog");
14+
}
15+
16+
@Override
17+
public File[] getAllLogFile() {
18+
return new File[]{logFile};
19+
}
20+
21+
@Override
22+
public File getFileByPos(final BlockPos blockPos) {
23+
return logFile;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package ru.lionzxy.fastlogblock.io.log;
2+
3+
public enum BlockChangeType {
4+
INSERT(0),
5+
REMOVE(1),
6+
UPDATE(2),
7+
UNKNOWN(100);
8+
private final byte typeId;
9+
10+
BlockChangeType(final int typeid) {
11+
this.typeId = (byte) typeid;
12+
}
13+
14+
public byte getTypeId() {
15+
return typeId;
16+
}
17+
18+
public static BlockChangeType valueOf(final byte typeId) {
19+
for (final BlockChangeType blockChangeType : BlockChangeType.values()) {
20+
if (blockChangeType.getTypeId() == typeId) {
21+
return blockChangeType;
22+
}
23+
}
24+
return null;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package ru.lionzxy.fastlogblock.io.log;
2+
3+
import gnu.trove.list.array.TByteArrayList;
4+
import gnu.trove.map.TIntObjectMap;
5+
import gnu.trove.map.TLongObjectMap;
6+
import gnu.trove.set.TIntSet;
7+
import gnu.trove.set.TLongSet;
8+
import gnu.trove.set.hash.TIntHashSet;
9+
import gnu.trove.set.hash.TLongHashSet;
10+
import net.minecraft.util.math.BlockPos;
11+
import net.minecraftforge.fml.common.FMLLog;
12+
import ru.lionzxy.fastlogblock.io.base.IterrateByteFile;
13+
import ru.lionzxy.fastlogblock.io.mappers.BlockMapper;
14+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
15+
import ru.lionzxy.fastlogblock.models.ASCIString;
16+
import ru.lionzxy.fastlogblock.models.BlockChangeEventModel;
17+
import ru.lionzxy.fastlogblock.models.PrepareReadBlockChangeEvent;
18+
import ru.lionzxy.fastlogblock.utils.CollectionUtils;
19+
import ru.lionzxy.fastlogblock.utils.Constants;
20+
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.io.OutputStream;
24+
import java.nio.ByteBuffer;
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
import java.util.stream.Collectors;
28+
29+
public class LogReader extends IterrateByteFile {
30+
private final BlockMapper blockMapper;
31+
private final NickMapper nickMapper;
32+
33+
public LogReader(final File file, final BlockMapper blockMapper, final NickMapper nickMapper) {
34+
super(file);
35+
this.blockMapper = blockMapper;
36+
this.nickMapper = nickMapper;
37+
}
38+
39+
40+
public List<BlockChangeEventModel> readEventByPos(final BlockPos blockPos) throws IOException {
41+
FMLLog.log.warn("readEventByPos() has very long execution time!");
42+
43+
final int needPosX = blockPos.getX();
44+
final int needPosY = blockPos.getY();
45+
final int needPosZ = blockPos.getZ();
46+
47+
final List<PrepareReadBlockChangeEvent> prepareEvents = new ArrayList<>();
48+
final TLongSet needBlockName = new TLongHashSet();
49+
final TIntSet needNickName = new TIntHashSet();
50+
iterateByFile((byteList) -> {
51+
final PrepareReadBlockChangeEvent prepareReadBlockChangeEvent = prepareOrNullByPos(byteList.toArray(),
52+
needPosX, needPosY, needPosZ);
53+
if (prepareReadBlockChangeEvent == null) {
54+
return;
55+
}
56+
57+
needBlockName.add(prepareReadBlockChangeEvent.getBlockId());
58+
needNickName.add(prepareReadBlockChangeEvent.getPlayerid());
59+
60+
prepareEvents.add(prepareReadBlockChangeEvent);
61+
});
62+
63+
final TIntObjectMap<ASCIString> idToNick = CollectionUtils.toHashMap(needNickName, id -> nickMapper.getById(id));
64+
final TLongObjectMap<ASCIString> idToBlock = blockMapper.idsToNames(needBlockName);
65+
66+
return prepareEvents.stream().map(pE -> pE.toBlockChangeEventModel(idToNick, idToBlock)).collect(Collectors.toList());
67+
}
68+
69+
private PrepareReadBlockChangeEvent prepareOrNullByPos(final byte[] bytes, final int needPosX, final int needPosY, final int needPosZ) {
70+
final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
71+
final int posX = byteBuffer.getInt();
72+
if (posX != needPosX) {
73+
return null;
74+
}
75+
final int posY = byteBuffer.getInt();
76+
if (posY != needPosY) {
77+
return null;
78+
}
79+
final int posZ = byteBuffer.getInt();
80+
if (posZ != needPosZ) {
81+
return null;
82+
}
83+
final BlockChangeType blockChangeType = BlockChangeType.valueOf(byteBuffer.get());
84+
final int playerId = byteBuffer.getInt();
85+
final long blockId = byteBuffer.getLong();
86+
final long timestamp = byteBuffer.getLong();
87+
88+
return new PrepareReadBlockChangeEvent(posX, posY, posZ, blockId, playerId, timestamp, blockChangeType);
89+
}
90+
91+
@Override
92+
protected void writeToFile(final OutputStream outputStream) throws IOException {
93+
// nothing
94+
}
95+
96+
@Override
97+
public void sync() throws IOException {
98+
// nothing
99+
}
100+
101+
@Override
102+
protected boolean checkLineEnd(final TByteArrayList arrayList, final byte endByte) {
103+
return arrayList.size() == Constants.SIZE_LOGLINE;
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ru.lionzxy.fastlogblock.io.log;
2+
3+
import ru.lionzxy.fastlogblock.io.mappers.BlockMapper;
4+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
5+
import ru.lionzxy.fastlogblock.models.BlockChangeEventModel;
6+
import ru.lionzxy.fastlogblock.utils.Constants;
7+
import ru.lionzxy.fastlogblock.utils.FileUtils;
8+
9+
import java.io.BufferedOutputStream;
10+
import java.io.File;
11+
import java.io.FileOutputStream;
12+
import java.io.IOException;
13+
import java.nio.ByteBuffer;
14+
15+
public class LogWritter {
16+
private BufferedOutputStream os;
17+
private final BlockMapper blockMapper;
18+
private final NickMapper nickMapper;
19+
private final File file;
20+
21+
public LogWritter(final File file, final BlockMapper blockMapper, final NickMapper nickMapper) throws IOException {
22+
this.file = file;
23+
this.blockMapper = blockMapper;
24+
this.nickMapper = nickMapper;
25+
26+
FileUtils.createFileIfNotExist(file);
27+
28+
os = new BufferedOutputStream(new FileOutputStream(file, true));
29+
}
30+
31+
/**
32+
* Name posX posY posZ typeaction playerid blockid timestamp
33+
*
34+
* @param blockChangeEventModel
35+
*/
36+
public void putEvent(final BlockChangeEventModel blockChangeEventModel) {
37+
final ByteBuffer byteBuffer = ByteBuffer.allocate(Constants.SIZE_LOGLINE);
38+
byteBuffer.putInt(blockChangeEventModel.getPosX());
39+
byteBuffer.putInt(blockChangeEventModel.getPosY());
40+
byteBuffer.putInt(blockChangeEventModel.getPosZ());
41+
byteBuffer.put(blockChangeEventModel.getBlockChangeType().getTypeId());
42+
byteBuffer.putInt(nickMapper.getOrPutUser(blockChangeEventModel.getPlayernick()));
43+
byteBuffer.putLong(blockMapper.getOrPutBlock(blockChangeEventModel.getNameblock()));
44+
byteBuffer.putLong(blockChangeEventModel.getTimestamp().getTime());
45+
46+
try {
47+
os.write(byteBuffer.array());
48+
} catch (final IOException e) {
49+
try {
50+
sync();
51+
os.write(byteBuffer.array());
52+
} catch (final IOException ioe) {
53+
ioe.printStackTrace();
54+
}
55+
}
56+
}
57+
58+
public void sync() throws IOException {
59+
FileUtils.createFileIfNotExist(file);
60+
61+
try {
62+
os.flush();
63+
} catch (final IOException e) {
64+
os = new BufferedOutputStream(new FileOutputStream(file, true));
65+
os.flush();
66+
}
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package ru.lionzxy.fastlogblock.io.mappers;
2+
3+
import com.google.common.annotations.VisibleForTesting;
4+
import gnu.trove.TObjectLongHashMap;
5+
import gnu.trove.list.array.TByteArrayList;
6+
import gnu.trove.map.TLongObjectMap;
7+
import gnu.trove.map.hash.TLongObjectHashMap;
8+
import gnu.trove.set.TLongSet;
9+
import ru.lionzxy.fastlogblock.io.base.IterrateByteFile;
10+
import ru.lionzxy.fastlogblock.models.ASCIString;
11+
12+
import java.io.File;
13+
import java.io.IOException;
14+
import java.io.OutputStream;
15+
import java.nio.ByteBuffer;
16+
import java.util.concurrent.atomic.AtomicLong;
17+
import java.util.concurrent.locks.ReentrantReadWriteLock;
18+
19+
import static ru.lionzxy.fastlogblock.utils.Constants.DEVIDER_SYMBOL;
20+
21+
22+
/**
23+
* id : blockname
24+
*/
25+
public class BlockMapper extends IterrateByteFile {
26+
private final AtomicLong maxId = new AtomicLong(Long.MIN_VALUE);
27+
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
28+
private final TObjectLongHashMap blockToId = new TObjectLongHashMap();
29+
30+
@VisibleForTesting
31+
public BlockMapper() {
32+
super(null);
33+
}
34+
35+
public BlockMapper(final File mapFile) throws IOException {
36+
super(mapFile);
37+
this.iterateByFile(this::putFromByte);
38+
}
39+
40+
@Override
41+
protected void writeToFile(final OutputStream outputStream) throws IOException {
42+
blockToId.forEachEntry((o, i) -> {
43+
final ByteBuffer byteBuffer = ByteBuffer.allocate(Long.BYTES + 1 + ((ASCIString) o).getShortString().length);
44+
byteBuffer.putLong(i);
45+
byteBuffer.put(((ASCIString) o).getShortString());
46+
byteBuffer.put(DEVIDER_SYMBOL);
47+
try {
48+
outputStream.write(byteBuffer.array());
49+
} catch (final IOException e) {
50+
e.printStackTrace();
51+
}
52+
return true;
53+
});
54+
outputStream.flush();
55+
}
56+
57+
private void putFromByte(final TByteArrayList byteArrayList) {
58+
final ByteBuffer byteBuffer = ByteBuffer.wrap(byteArrayList.toArray());
59+
final long blockid = byteBuffer.getLong();
60+
61+
final byte[] tmpbuffer = new byte[byteArrayList.size() - Long.BYTES - 1];
62+
byteBuffer.get(tmpbuffer);
63+
final ASCIString asciString = new ASCIString(tmpbuffer);
64+
blockToId.put(asciString, blockid);
65+
if (blockid > maxId.get()) {
66+
maxId.set(blockid);
67+
}
68+
}
69+
70+
public long getOrPutBlock(final ASCIString newBlock) {
71+
readWriteLock.readLock().lock();
72+
try {
73+
final long blockid = blockToId.get(newBlock);
74+
if (blockid != 0) {
75+
return blockid;
76+
}
77+
} finally {
78+
readWriteLock.readLock().unlock();
79+
}
80+
81+
return putBlock(newBlock);
82+
}
83+
84+
private long putBlock(final ASCIString newBlock) {
85+
readWriteLock.writeLock().lock();
86+
try {
87+
long blockid = blockToId.get(newBlock);
88+
if (blockid != 0) {
89+
return blockid;
90+
}
91+
92+
blockid = maxId.incrementAndGet();
93+
if (blockid == 0) {
94+
blockid++;
95+
maxId.getAndIncrement();
96+
}
97+
blockToId.put(newBlock, blockid);
98+
markDirty.set(true);
99+
return blockid;
100+
} finally {
101+
readWriteLock.writeLock().unlock();
102+
}
103+
}
104+
105+
public TLongObjectMap<ASCIString> idsToNames(final TLongSet longSet) {
106+
final TLongObjectMap<ASCIString> toReturn = new TLongObjectHashMap<>();
107+
108+
try {
109+
readWriteLock.readLock().lock();
110+
blockToId.forEachEntry((blockname, id) -> {
111+
if(!longSet.contains(id)){
112+
return true;
113+
}
114+
toReturn.put(id, (ASCIString) blockname);
115+
return true;
116+
});
117+
} finally {
118+
readWriteLock.readLock().unlock();
119+
}
120+
121+
return toReturn;
122+
}
123+
124+
@VisibleForTesting
125+
public int size() {
126+
try {
127+
readWriteLock.readLock().lock();
128+
return blockToId.size();
129+
} finally {
130+
readWriteLock.readLock().unlock();
131+
}
132+
}
133+
134+
@Override
135+
protected boolean checkLineEnd(final TByteArrayList arrayList, final byte endByte) {
136+
return endByte == DEVIDER_SYMBOL;
137+
}
138+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package ru.lionzxy.fastlogblock.io.mappers;
2+
3+
import com.google.common.annotations.VisibleForTesting;
4+
import gnu.trove.TIntObjectHashMap;
5+
import gnu.trove.TObjectIntHashMap;
6+
import gnu.trove.list.array.TByteArrayList;
7+
import ru.lionzxy.fastlogblock.io.base.IterrateByteFile;
8+
import ru.lionzxy.fastlogblock.models.ASCIString;
9+
import ru.lionzxy.fastlogblock.utils.Constants;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.io.OutputStream;
14+
import java.nio.ByteBuffer;
15+
import java.util.concurrent.atomic.AtomicInteger;
16+
17+
import static ru.lionzxy.fastlogblock.utils.Constants.DEVIDER_SYMBOL;
18+
19+
public class NickMapper extends IterrateByteFile {
20+
private final AtomicInteger maxId = new AtomicInteger(Integer.MIN_VALUE);
21+
private final TObjectIntHashMap uuidToId = new TObjectIntHashMap();
22+
private final TIntObjectHashMap idToObject = new TIntObjectHashMap();
23+
24+
@VisibleForTesting
25+
public NickMapper() {
26+
super(null);
27+
}
28+
29+
public NickMapper(final File mapFile) throws IOException {
30+
super(mapFile);
31+
this.iterateByFile(this::putFromByte);
32+
}
33+
34+
private void putFromByte(final TByteArrayList byteArrayList) {
35+
final ByteBuffer byteBuffer = ByteBuffer.wrap(byteArrayList.toArray());
36+
final int userid = byteBuffer.getInt();
37+
38+
final byte[] tmpbuffer = new byte[byteArrayList.size() - 5];
39+
byteBuffer.get(tmpbuffer);
40+
final ASCIString asciString = new ASCIString(tmpbuffer);
41+
uuidToId.put(asciString, userid);
42+
idToObject.put(userid, asciString);
43+
if (userid > maxId.get()) {
44+
maxId.set(userid);
45+
}
46+
}
47+
48+
@Override
49+
protected void writeToFile(final OutputStream outputStream) throws IOException {
50+
idToObject.forEachEntry((i, o) -> {
51+
final ByteBuffer byteBuffer = ByteBuffer.allocate(5 + ((ASCIString) o).getShortString().length);
52+
byteBuffer.putInt(i);
53+
byteBuffer.put(((ASCIString) o).getShortString());
54+
byteBuffer.put(DEVIDER_SYMBOL);
55+
try {
56+
outputStream.write(byteBuffer.array());
57+
} catch (final IOException e) {
58+
e.printStackTrace();
59+
}
60+
return true;
61+
});
62+
outputStream.flush();
63+
}
64+
65+
66+
public int getOrPutUser(final ASCIString newUser) {
67+
readWriteLock.readLock().lock();
68+
try {
69+
final int userid = uuidToId.get(newUser);
70+
if (userid != 0) {
71+
return userid;
72+
}
73+
} finally {
74+
readWriteLock.readLock().unlock();
75+
}
76+
77+
return putUser(newUser);
78+
}
79+
80+
public ASCIString getById(final int id) {
81+
readWriteLock.readLock().lock();
82+
try {
83+
return (ASCIString) idToObject.get(id);
84+
} finally {
85+
readWriteLock.readLock().unlock();
86+
}
87+
}
88+
89+
90+
private int putUser(final ASCIString newUser) {
91+
readWriteLock.writeLock().lock();
92+
try {
93+
int userid = uuidToId.get(newUser);
94+
if (userid != 0) {
95+
return userid;
96+
}
97+
98+
userid = maxId.incrementAndGet();
99+
if (userid == 0) {
100+
userid++;
101+
maxId.getAndIncrement();
102+
}
103+
uuidToId.put(newUser, userid);
104+
idToObject.put(userid, newUser);
105+
markDirty.set(true);
106+
return userid;
107+
} finally {
108+
readWriteLock.writeLock().unlock();
109+
}
110+
}
111+
112+
@VisibleForTesting
113+
public int size() {
114+
try {
115+
readWriteLock.readLock().lock();
116+
if (uuidToId.size() != idToObject.size()) {
117+
return -1;
118+
}
119+
return uuidToId.size();
120+
} finally {
121+
readWriteLock.readLock().unlock();
122+
}
123+
}
124+
125+
@Override
126+
protected boolean checkLineEnd(final TByteArrayList arrayList, final byte endByte) {
127+
return endByte == Constants.DEVIDER_SYMBOL;
128+
}
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package ru.lionzxy.fastlogblock.models;
2+
3+
import java.nio.charset.Charset;
4+
5+
public class ASCIString implements CharSequence {
6+
private final byte[] shortString;
7+
private int hashcode = -1;
8+
private final static Charset asci = Charset.forName("ASCII");
9+
10+
public ASCIString(final byte[] fatString) {
11+
shortString = fatString;
12+
13+
initHash();
14+
}
15+
16+
public ASCIString(final String fatString) {
17+
shortString = fatString.getBytes(asci);
18+
19+
initHash();
20+
}
21+
22+
@Override
23+
public int length() {
24+
return shortString.length;
25+
}
26+
27+
@Override
28+
public char charAt(final int index) {
29+
return (char) shortString[index];
30+
}
31+
32+
@Override
33+
public CharSequence subSequence(final int start, final int end) {
34+
return new String(shortString, asci).subSequence(start, end);
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
if (hashcode == -1) {
40+
initHash();
41+
}
42+
return hashcode;
43+
}
44+
45+
@Override
46+
public boolean equals(final Object obj) {
47+
if (!(obj instanceof ASCIString)) {
48+
return false;
49+
}
50+
final byte[] alienBytes = ((ASCIString) obj).shortString;
51+
if (alienBytes.length != shortString.length) {
52+
return false;
53+
}
54+
for (int i = 0; i < alienBytes.length; i++) {
55+
if (alienBytes[i] != shortString[i]) {
56+
return false;
57+
}
58+
}
59+
return true;
60+
}
61+
62+
@Override
63+
public String toString() {
64+
return new String(shortString, asci);
65+
}
66+
67+
public byte[] getShortString() {
68+
return shortString;
69+
}
70+
71+
private void initHash() {
72+
int h = 0;
73+
for (int i = 0; i < length(); i++) {
74+
h = 31 * h + shortString[i];
75+
}
76+
hashcode = h;
77+
}
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package ru.lionzxy.fastlogblock.models;
2+
3+
import jline.internal.Nullable;
4+
import net.minecraft.util.ResourceLocation;
5+
import net.minecraft.util.math.BlockPos;
6+
import net.minecraftforge.event.world.BlockEvent;
7+
import ru.lionzxy.fastlogblock.io.log.BlockChangeType;
8+
9+
import java.sql.Timestamp;
10+
11+
public class BlockChangeEventModel {
12+
private final int posX, posY, posZ;
13+
private final ASCIString nameblock;
14+
private final ASCIString playernick;
15+
private final BlockChangeType blockChangeType;
16+
private final Timestamp timestamp;
17+
18+
public BlockChangeEventModel(final BlockPos blockPos,
19+
final String nameblock,
20+
final String playernick,
21+
final Timestamp timestamp,
22+
final BlockChangeType blockChangeType) {
23+
this.posX = blockPos.getX();
24+
this.posY = blockPos.getY();
25+
this.posZ = blockPos.getZ();
26+
27+
this.nameblock = new ASCIString(nameblock);
28+
this.playernick = new ASCIString(playernick);
29+
30+
this.blockChangeType = blockChangeType;
31+
this.timestamp = timestamp;
32+
}
33+
34+
@Nullable
35+
public static BlockChangeEventModel getChangeEvent(final BlockEvent blockEvent) {
36+
final ResourceLocation rl = blockEvent.getState().getBlock().getRegistryName();
37+
38+
final int meta = blockEvent.getState().getBlock().getMetaFromState(blockEvent.getState());
39+
40+
if (rl == null) {
41+
return null;
42+
}
43+
44+
final String blockid = "<" + rl.getResourceDomain()
45+
+ ":" + rl.getResourcePath() +
46+
":" + meta + ">";
47+
48+
final BlockChangeType blockChangeType;
49+
final String playername;
50+
if (blockEvent instanceof BlockEvent.BreakEvent) {
51+
blockChangeType = BlockChangeType.REMOVE;
52+
playername = ((BlockEvent.BreakEvent) blockEvent).getPlayer().getUniqueID().toString();
53+
} else if (blockEvent instanceof BlockEvent.PlaceEvent) {
54+
blockChangeType = BlockChangeType.INSERT;
55+
playername = ((BlockEvent.PlaceEvent) blockEvent).getPlayer().getUniqueID().toString();
56+
57+
} else {
58+
return null;
59+
}
60+
61+
final Timestamp timestamp = new Timestamp(System.currentTimeMillis());
62+
63+
return new BlockChangeEventModel(blockEvent.getPos(), blockid, playername, timestamp, blockChangeType);
64+
}
65+
66+
public int getPosX() {
67+
return posX;
68+
}
69+
70+
public int getPosY() {
71+
return posY;
72+
}
73+
74+
public int getPosZ() {
75+
return posZ;
76+
}
77+
78+
public ASCIString getNameblock() {
79+
return nameblock;
80+
}
81+
82+
public ASCIString getPlayernick() {
83+
return playernick;
84+
}
85+
86+
public BlockChangeType getBlockChangeType() {
87+
return blockChangeType;
88+
}
89+
90+
public Timestamp getTimestamp() {
91+
return timestamp;
92+
}
93+
94+
@Override
95+
public String toString() {
96+
return "BlockChangeEventModel{" +
97+
"posX=" + posX +
98+
", posY=" + posY +
99+
", posZ=" + posZ +
100+
", nameblock=" + nameblock +
101+
", playernick=" + playernick +
102+
", blockChangeType=" + blockChangeType +
103+
", timestamp=" + timestamp +
104+
'}';
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package ru.lionzxy.fastlogblock.models;
2+
3+
import gnu.trove.map.TIntObjectMap;
4+
import gnu.trove.map.TLongObjectMap;
5+
import net.minecraft.util.math.BlockPos;
6+
import ru.lionzxy.fastlogblock.io.log.BlockChangeType;
7+
8+
import java.sql.Timestamp;
9+
10+
public class PrepareReadBlockChangeEvent {
11+
private final int posX;
12+
private final int posY;
13+
private final int posZ;
14+
private final long blockId;
15+
private final int playerid;
16+
private final long timestamp;
17+
private final BlockChangeType blockChangeType;
18+
19+
public PrepareReadBlockChangeEvent(final int posX, final int posY, final int posZ,
20+
final long blockid,
21+
final int playerid,
22+
final long timestamp,
23+
final BlockChangeType blockChangeType) {
24+
this.posX = posX;
25+
this.posY = posY;
26+
this.posZ = posZ;
27+
this.blockId = blockid;
28+
this.playerid = playerid;
29+
this.timestamp = timestamp;
30+
this.blockChangeType = blockChangeType;
31+
}
32+
33+
public long getBlockId() {
34+
return blockId;
35+
}
36+
37+
public int getPlayerid() {
38+
return playerid;
39+
}
40+
41+
public BlockChangeEventModel toBlockChangeEventModel(final TIntObjectMap<ASCIString> idToNick, final TLongObjectMap<ASCIString> idToBlock) {
42+
return new BlockChangeEventModel(new BlockPos(posX, posY, posZ),
43+
idToBlock.get(blockId).toString(),
44+
idToNick.get(playerid).toString(),
45+
new Timestamp(timestamp),
46+
blockChangeType);
47+
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package ru.lionzxy.fastlogblock.utils;
2+
3+
import gnu.trove.map.TIntObjectMap;
4+
import gnu.trove.map.hash.TIntObjectHashMap;
5+
import gnu.trove.set.TIntSet;
6+
7+
import java.util.function.Function;
8+
9+
public class CollectionUtils {
10+
11+
public static <T> TIntObjectMap<T> toHashMap(final TIntSet set, final Function<Integer, T> mapper) {
12+
final TIntObjectMap<T> toReturn = new TIntObjectHashMap<>();
13+
14+
set.forEach((i) -> {
15+
toReturn.put(i, mapper.apply(i));
16+
return true;
17+
});
18+
19+
return toReturn;
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package ru.lionzxy.fastlogblock.utils;
2+
3+
public class Constants {
4+
public static final int SIZE_LOGLINE = Integer.BYTES * 4 + Long.BYTES * 2 + Byte.BYTES;
5+
public static final byte DEVIDER_SYMBOL = 28;
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package ru.lionzxy.fastlogblock.utils;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
6+
public class FileUtils {
7+
public static final int BYTEBUFFERSIZE = 2048;
8+
9+
public static void createFileIfNotExist(final File file) throws IOException {
10+
if (!file.exists()) {
11+
if (file.getParentFile() != null && !file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
12+
throw new IOException("Can't create dir to file " + file.getParentFile().getAbsolutePath());
13+
}
14+
if (!file.createNewFile()) {
15+
throw new IOException("Can't create file " + file.getAbsolutePath());
16+
}
17+
}
18+
}
19+
}

‎src/main/resources/mcmod.info

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"modid": "fastlogblock",
4+
"name": "Fast Log Block",
5+
"description": "Mod for logging block place and break",
6+
"version": "${version}",
7+
"mcversion": "${mcversion}",
8+
"url": "",
9+
"updateUrl": "",
10+
"authorList": [
11+
"LionZXYY"
12+
],
13+
"credits": "The Forge and FML guys, for making Forge ;)",
14+
"logoFile": "",
15+
"screenshots": [],
16+
"dependencies": []
17+
}
18+
]

‎src/main/resources/pack.mcmeta

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"pack": {
3+
"description": "examplemod resources",
4+
"pack_format": 3,
5+
"_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import com.google.testing.threadtester.*;
4+
import junit.framework.TestCase;
5+
import ru.lionzxy.fastlogblock.io.mappers.BlockMapper;
6+
import ru.lionzxy.fastlogblock.models.ASCIString;
7+
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
12+
public class BlockMapperAsyncTest extends TestCase {
13+
private volatile BlockMapper blockMapper;
14+
15+
public void testNickMapper() {
16+
final AnnotatedTestRunner runner = new AnnotatedTestRunner();
17+
runner.runTests(this.getClass(), BlockMapper.class);
18+
}
19+
20+
@ThreadedBefore
21+
public void before() throws IOException {
22+
blockMapper = new BlockMapper();
23+
}
24+
25+
@ThreadedMain
26+
public void main() {
27+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
28+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
29+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
30+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
31+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
32+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
33+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
34+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
35+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
36+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
37+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
38+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
39+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
40+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
41+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
42+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
43+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
44+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
45+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
46+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
47+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
48+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
49+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
50+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
51+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
52+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
53+
}
54+
55+
56+
@ThreadedSecondary
57+
public void secondary() {
58+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
59+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
60+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
61+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
62+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
63+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
64+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
65+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
66+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
67+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
68+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
69+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
70+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
71+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
72+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
73+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
74+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
75+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
76+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
77+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
78+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
79+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
80+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
81+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
82+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
83+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
84+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
85+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
86+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
87+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
88+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
89+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
90+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
91+
92+
}
93+
94+
@ThreadedAfter
95+
public void after() {
96+
final long first = blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
97+
final long second = blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
98+
final long third = blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
99+
assertEquals(3, blockMapper.size());
100+
assertEquals(Long.MIN_VALUE + 3, Collections.max(Arrays.asList(first, second, third)).longValue());
101+
}
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import junit.framework.TestCase;
4+
import ru.lionzxy.fastlogblock.io.mappers.BlockMapper;
5+
import ru.lionzxy.fastlogblock.models.ASCIString;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
12+
public class BlockMapperSaveTest extends TestCase {
13+
private BlockMapper blockMapper;
14+
private File testFile;
15+
16+
private void before() throws IOException {
17+
testFile = new File("./test.bytelog");
18+
this.blockMapper = new BlockMapper(testFile);
19+
}
20+
21+
private void fill() {
22+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
23+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
24+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
25+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
26+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
27+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
28+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
29+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
30+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
31+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
32+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
33+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
34+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
35+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
36+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
37+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
38+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
39+
blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
40+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
41+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
42+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
43+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
44+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
45+
blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
46+
blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
47+
}
48+
49+
public void testSave() throws IOException {
50+
before();
51+
52+
final long first = blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>"));
53+
final long second = blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>"));
54+
final long third = blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>"));
55+
blockMapper.sync();
56+
blockMapper = new BlockMapper(testFile);
57+
assertEquals(first, blockMapper.getOrPutBlock(new ASCIString("<minecraft:test:1>")));
58+
assertEquals(second, blockMapper.getOrPutBlock(new ASCIString("<alpha:something:1>")));
59+
assertEquals(third, blockMapper.getOrPutBlock(new ASCIString("<openblock:so:3214>")));
60+
final long max = Collections.max(Arrays.asList(first, second, third));
61+
assertEquals(max + 1, blockMapper.getOrPutBlock(new ASCIString("other")));
62+
after();
63+
}
64+
65+
private void after() throws IOException {
66+
assertTrue(testFile.delete());
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import junit.framework.TestCase;
4+
import net.minecraft.util.math.BlockPos;
5+
import ru.lionzxy.fastlogblock.io.log.BlockChangeType;
6+
import ru.lionzxy.fastlogblock.io.log.LogReader;
7+
import ru.lionzxy.fastlogblock.io.log.LogWritter;
8+
import ru.lionzxy.fastlogblock.io.mappers.BlockMapper;
9+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
10+
import ru.lionzxy.fastlogblock.models.BlockChangeEventModel;
11+
12+
import java.io.File;
13+
import java.io.IOException;
14+
import java.sql.Timestamp;
15+
import java.util.List;
16+
17+
public class LogTest extends TestCase {
18+
private BlockMapper blockMapper;
19+
private NickMapper nickMapper;
20+
private final File logFile = new File("log.bytelog");
21+
private LogWritter logWritter;
22+
23+
24+
private void before() throws IOException {
25+
new File("blockmap.bytelog").delete();
26+
new File("nickmap.bytelog").delete();
27+
logFile.delete();
28+
blockMapper = new BlockMapper(new File("blockmap.bytelog"));
29+
nickMapper = new NickMapper(new File("nickmap.bytelog"));
30+
logWritter = new LogWritter(logFile, blockMapper, nickMapper);
31+
}
32+
33+
private void fillLog() {
34+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(-2, 3, 5),
35+
"<minecraft:block:1>", "LionZXY",
36+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
37+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(8, 9, 10),
38+
"<mode:block>", "SomeNickname",
39+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
40+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(10, 3, 2),
41+
"<mod:blok:2>", "LionZXY",
42+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
43+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(20, 40, 5),
44+
"<somemode:block:3>", "SomeNickname2",
45+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
46+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(-2, 3, 5),
47+
"<oh:sad:0>", "Typical",
48+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
49+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(-2, 3, 5),
50+
"<minecraft:block:1>", "LionZXY",
51+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
52+
logWritter.putEvent(new BlockChangeEventModel(new BlockPos(-2, 3, 5),
53+
"<minecraft:block:1>", "LionZXY",
54+
new Timestamp(System.currentTimeMillis()), BlockChangeType.INSERT));
55+
}
56+
57+
public void testLog() throws IOException {
58+
before();
59+
for (int i = 0; i < 1000; i++) {
60+
fillLog();
61+
}
62+
logWritter.sync();
63+
64+
final LogReader logReader = new LogReader(logFile, blockMapper, nickMapper);
65+
66+
final List<BlockChangeEventModel> blockChangeEventModels = logReader.readEventByPos(new BlockPos(10, 3, 2));
67+
68+
assertEquals(1000, blockChangeEventModels.size());
69+
70+
after();
71+
}
72+
73+
74+
private void after() throws IOException {
75+
blockMapper.sync();
76+
nickMapper.sync();
77+
logWritter.sync();
78+
79+
new File("blockmap.bytelog").delete();
80+
new File("nickmap.bytelog").delete();
81+
logFile.delete();
82+
}
83+
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import com.google.testing.threadtester.*;
4+
import junit.framework.TestCase;
5+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
6+
import ru.lionzxy.fastlogblock.models.ASCIString;
7+
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
12+
public class NickMapperAsyncTest extends TestCase {
13+
private volatile NickMapper nickMapper;
14+
15+
public void testNickMapper() {
16+
final AnnotatedTestRunner runner = new AnnotatedTestRunner();
17+
runner.runTests(this.getClass(), NickMapper.class);
18+
}
19+
20+
@ThreadedBefore
21+
public void before() throws IOException {
22+
nickMapper = new NickMapper();
23+
}
24+
25+
@ThreadedMain
26+
public void main() {
27+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
28+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
29+
nickMapper.getOrPutUser(new ASCIString("3"));
30+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
31+
nickMapper.getOrPutUser(new ASCIString("2"));
32+
nickMapper.getOrPutUser(new ASCIString("2"));
33+
nickMapper.getOrPutUser(new ASCIString("2"));
34+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
35+
nickMapper.getOrPutUser(new ASCIString("2"));
36+
nickMapper.getOrPutUser(new ASCIString("2"));
37+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
38+
nickMapper.getOrPutUser(new ASCIString("2"));
39+
nickMapper.getOrPutUser(new ASCIString("2"));
40+
}
41+
42+
43+
@ThreadedSecondary
44+
public void secondary() {
45+
nickMapper.getOrPutUser(new ASCIString("2"));
46+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
47+
nickMapper.getOrPutUser(new ASCIString("3"));
48+
nickMapper.getOrPutUser(new ASCIString("3"));
49+
nickMapper.getOrPutUser(new ASCIString("2"));
50+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
51+
nickMapper.getOrPutUser(new ASCIString("2"));
52+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
53+
nickMapper.getOrPutUser(new ASCIString("3"));
54+
nickMapper.getOrPutUser(new ASCIString("2"));
55+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
56+
57+
}
58+
59+
@ThreadedAfter
60+
public void after() {
61+
final int first = nickMapper.getOrPutUser(new ASCIString("LionZXY"));
62+
final int second = nickMapper.getOrPutUser(new ASCIString("2"));
63+
final int third = nickMapper.getOrPutUser(new ASCIString("3"));
64+
assertEquals(3, nickMapper.size());
65+
assertEquals(Integer.MIN_VALUE + 3, Collections.max(Arrays.asList(first, second, third)).intValue());
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package ru.lionzxy.fastlogblock.io;
2+
3+
import junit.framework.TestCase;
4+
import ru.lionzxy.fastlogblock.io.mappers.NickMapper;
5+
import ru.lionzxy.fastlogblock.models.ASCIString;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
12+
public class NickMapperSaveTest extends TestCase {
13+
private NickMapper nickMapper;
14+
private File testFile;
15+
16+
private void before() throws IOException {
17+
testFile = new File("./test.bytelog");
18+
this.nickMapper = new NickMapper(testFile);
19+
}
20+
21+
public void testSave() throws IOException {
22+
before();
23+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
24+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
25+
nickMapper.getOrPutUser(new ASCIString("3"));
26+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
27+
nickMapper.getOrPutUser(new ASCIString("2"));
28+
nickMapper.getOrPutUser(new ASCIString("2"));
29+
nickMapper.getOrPutUser(new ASCIString("2"));
30+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
31+
nickMapper.getOrPutUser(new ASCIString("2"));
32+
nickMapper.getOrPutUser(new ASCIString("2"));
33+
nickMapper.getOrPutUser(new ASCIString("LionZXY"));
34+
nickMapper.getOrPutUser(new ASCIString("2"));
35+
nickMapper.getOrPutUser(new ASCIString("2"));
36+
37+
38+
final int first = nickMapper.getOrPutUser(new ASCIString("LionZXY"));
39+
final int second = nickMapper.getOrPutUser(new ASCIString("2"));
40+
final int third = nickMapper.getOrPutUser(new ASCIString("3"));
41+
nickMapper.sync();
42+
nickMapper = new NickMapper(testFile);
43+
assertEquals(first, nickMapper.getOrPutUser(new ASCIString("LionZXY")));
44+
assertEquals(second, nickMapper.getOrPutUser(new ASCIString("2")));
45+
assertEquals(third, nickMapper.getOrPutUser(new ASCIString("3")));
46+
final int max = Collections.max(Arrays.asList(first, second, third));
47+
assertEquals(max + 1, nickMapper.getOrPutUser(new ASCIString("other")));
48+
after();
49+
}
50+
51+
private void after() throws IOException {
52+
assertTrue(testFile.delete());
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package ru.lionzxy.fastlogblock.utils;
2+
3+
import junit.framework.TestCase;
4+
import ru.lionzxy.fastlogblock.models.ASCIString;
5+
6+
public class ASCITest extends TestCase {
7+
public void testEquals() {
8+
final ASCIString str1 = new ASCIString(new String("Test"));
9+
final ASCIString str2 = new ASCIString("Test");
10+
assertEquals(str1, str2);
11+
assertEquals(str1.hashCode(), str2.hashCode());
12+
assertEquals(str1.toString(), "Test");
13+
}
14+
}

0 commit comments

Comments
 (0)
Please sign in to comment.