Skip to content

Commit 46d37d1

Browse files
committed
fix: blockdata key set failure
1 parent e9ed04f commit 46d37d1

File tree

3 files changed

+76
-36
lines changed

3 files changed

+76
-36
lines changed

src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/ASlimefunDataContainer.java

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.xzavier0722.mc.plugin.slimefun4.storage.controller;
22

3+
import java.util.Map;
4+
import java.util.WeakHashMap;
5+
import java.util.concurrent.ConcurrentHashMap;
6+
import javax.annotation.ParametersAreNonnullByDefault;
37
import lombok.Getter;
4-
import lombok.Setter;
58

69
/**
710
* Slimefun 数据容器的抽象类.
@@ -16,10 +19,69 @@ public abstract class ASlimefunDataContainer extends ADataContainer {
1619
@Getter
1720
private final String sfId;
1821

19-
@Setter
2022
@Getter
2123
private volatile boolean pendingRemove = false;
2224

25+
// use weak hash map to capture the pending remove datas, if it is removed finally, it will not cause memory leak
26+
private static final WeakHashMap<ASlimefunDataContainer, Map<String, String>> capturedPendingRemoveData =
27+
new WeakHashMap<>();
28+
29+
protected void setWhilePendingRemove(String key, String value) {
30+
if (pendingRemove) {
31+
Map<String, String> map;
32+
synchronized (capturedPendingRemoveData) {
33+
map = capturedPendingRemoveData.computeIfAbsent(this, (k) -> new ConcurrentHashMap<>());
34+
}
35+
map.put(key, value);
36+
}
37+
}
38+
39+
public void setPendingRemove(boolean val) {
40+
if (val) {
41+
pendingRemove = true;
42+
} else {
43+
// save keys during the remove
44+
pendingRemove = false;
45+
Map<String, String> map;
46+
synchronized (capturedPendingRemoveData) {
47+
map = capturedPendingRemoveData.remove(this);
48+
}
49+
if (map != null) {
50+
for (var entry : map.entrySet()) {
51+
setData(entry.getKey(), entry.getValue());
52+
}
53+
}
54+
}
55+
}
56+
57+
@ParametersAreNonnullByDefault
58+
public void setData(String key, String val) {
59+
checkData();
60+
setCacheInternal(key, val, true);
61+
if (isPendingRemove()) {
62+
// someone is modifying a removed blockData or a virtual blockData, DO NOT SAVE
63+
// save the key-value for other later use
64+
setWhilePendingRemove(key, val);
65+
return;
66+
} else {
67+
updateDataBaseKey(key);
68+
}
69+
}
70+
71+
@ParametersAreNonnullByDefault
72+
public void removeData(String key) {
73+
if (removeCacheInternal(key) != null || !isDataLoaded()) {
74+
if (isPendingRemove()) {
75+
setWhilePendingRemove(key, null);
76+
} else {
77+
updateDataBaseKey(key);
78+
}
79+
}
80+
}
81+
82+
@ParametersAreNonnullByDefault
83+
public abstract void updateDataBaseKey(String key);
84+
2385
public ASlimefunDataContainer(String key, String sfId) {
2486
super(key);
2587
this.sfId = sfId;

src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunBlockData.java

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,6 @@ public String getSfId() {
4848
return super.getSfId();
4949
}
5050

51-
@ParametersAreNonnullByDefault
52-
public void setData(String key, String val) {
53-
checkData();
54-
55-
if (isPendingRemove()) {
56-
// someone is modifying a removed blockData or a virtual blockData, DO NOT SAVE
57-
return;
58-
}
59-
60-
setCacheInternal(key, val, true);
61-
Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedBlockDataUpdate(this, key);
62-
}
63-
64-
@ParametersAreNonnullByDefault
65-
public void removeData(String key) {
66-
if (removeCacheInternal(key) != null || !isDataLoaded()) {
67-
Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedBlockDataUpdate(this, key);
68-
}
69-
}
70-
7151
@ParametersAreNullableByDefault
7252
void setBlockMenu(BlockMenu blockMenu) {
7353
menu = blockMenu;
@@ -93,4 +73,10 @@ void setBlockMenu(BlockMenu blockMenu) {
9373

9474
return re;
9575
}
76+
77+
@Override
78+
@ParametersAreNonnullByDefault
79+
public void updateDataBaseKey(String key) {
80+
Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedBlockDataUpdate(this, key);
81+
}
9682
}

src/main/java/com/xzavier0722/mc/plugin/slimefun4/storage/controller/SlimefunUniversalData.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,16 @@ public class SlimefunUniversalData extends ASlimefunDataContainer {
3737
@ParametersAreNonnullByDefault
3838
@SneakyThrows
3939
public void setData(String key, String val) {
40-
checkData();
41-
42-
if (isPendingRemove()) {
43-
throw new IllegalStateException("不能修改即将删除的方块数据");
44-
}
45-
4640
if (UniversalDataTrait.isReservedKey(key)) {
4741
throw new IllegalAccessException("不能修改当前受保护的方块数据键值对");
4842
}
4943

50-
setCacheInternal(key, val, true);
44+
super.setData(key, val);
45+
}
46+
47+
@Override
48+
@ParametersAreNonnullByDefault
49+
public void updateDataBaseKey(String key) {
5150
Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key);
5251
}
5352

@@ -64,13 +63,6 @@ protected void setTraitData(UniversalDataTrait trait, String val) {
6463
}
6564
}
6665

67-
@ParametersAreNonnullByDefault
68-
public void removeData(String key) {
69-
if (removeCacheInternal(key) != null || !isDataLoaded()) {
70-
Slimefun.getDatabaseManager().getBlockDataController().scheduleDelayedUniversalDataUpdate(this, key);
71-
}
72-
}
73-
7466
@Nullable public ItemStack[] getMenuContents() {
7567
if (menu == null) {
7668
return null;

0 commit comments

Comments
 (0)