Răsfoiți Sursa

Merge pull request #298 from Glitchfinder/master

Fixing conversion lag.
NuclearW 12 ani în urmă
părinte
comite
cd30771775

+ 1 - 1
src/main/java/com/gmail/nossr50/config/HiddenConfig.java

@@ -28,7 +28,7 @@ public class HiddenConfig {
         if (mcMMO.p.getResource(fileName) != null) {
             config = YamlConfiguration.loadConfiguration(mcMMO.p.getResource(fileName));
             chunkletsEnabled = config.getBoolean("Options.Chunklets", true);
-            conversionRate = config.getInt("Options.ConversionRate", 3);
+            conversionRate = config.getInt("Options.ConversionRate", 1);
         }
     }
 

+ 1 - 1
src/main/java/com/gmail/nossr50/runnables/blockstoreconversion/BlockStoreConversionZDirectory.java

@@ -15,7 +15,7 @@ import com.gmail.nossr50.util.blockmeta.HashChunkletManager;
 import com.gmail.nossr50.util.blockmeta.chunkmeta.HashChunkManager;
 
 public class BlockStoreConversionZDirectory implements Runnable {
-    private int taskID, cx, cz, x, y, z, y2, xPos, zPos, cxPos, czPos;
+    public int taskID, cx, cz, x, y, z, y2, xPos, zPos, cxPos, czPos;
     private String cxs, czs, chunkletName, chunkName;
     private org.bukkit.World world;
     private BukkitScheduler scheduler;

+ 54 - 99
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java

@@ -7,6 +7,7 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.OutputStream;
 import java.lang.Integer;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.UUID;
@@ -17,6 +18,7 @@ import org.bukkit.block.Block;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.ChunkletUnloader;
+import com.gmail.nossr50.runnables.blockstoreconversion.BlockStoreConversionZDirectory;
 import com.gmail.nossr50.util.blockmeta.ChunkletStore;
 import com.gmail.nossr50.util.blockmeta.PrimitiveChunkletStore;
 import com.gmail.nossr50.util.blockmeta.PrimitiveExChunkletStore;
@@ -27,9 +29,10 @@ import org.getspout.spoutapi.chunkstore.mcMMOSimpleRegionFile;
 public class HashChunkManager implements ChunkManager {
     private HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>> regionFiles = new HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>>();
     public HashMap<String, ChunkStore> store = new HashMap<String, ChunkStore>();
+    public ArrayList<BlockStoreConversionZDirectory> converters = new ArrayList<BlockStoreConversionZDirectory>();
 
     @Override
-    public void closeAll() {
+    public synchronized void closeAll() {
         for (UUID uid : regionFiles.keySet()) {
             HashMap<Long, mcMMOSimpleRegionFile> worldRegions = regionFiles.get(uid);
             Iterator<mcMMOSimpleRegionFile> itr = worldRegions.values().iterator();
@@ -45,7 +48,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public ChunkStore readChunkStore(World world, int x, int z) throws IOException {
+    public synchronized ChunkStore readChunkStore(World world, int x, int z) throws IOException {
         mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z);
         InputStream in = rf.getInputStream(x, z);
         if (in == null) {
@@ -72,7 +75,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void writeChunkStore(World world, int x, int z, ChunkStore data) {
+    public synchronized void writeChunkStore(World world, int x, int z, ChunkStore data) {
         if (!data.isDirty()) {
             return;
         }
@@ -89,14 +92,14 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void closeChunkStore(World world, int x, int z) {
+    public synchronized void closeChunkStore(World world, int x, int z) {
         mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z);
         if (rf != null) {
             rf.close();
         }
     }
 
-    private mcMMOSimpleRegionFile getSimpleRegionFile(World world, int x, int z) {
+    private synchronized mcMMOSimpleRegionFile getSimpleRegionFile(World world, int x, int z) {
         File directory = new File(world.getWorldFolder(), "mcmmo_regions");
 
         directory.mkdirs();
@@ -127,17 +130,17 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void loadChunklet(int cx, int cy, int cz, World world) {
+    public synchronized void loadChunklet(int cx, int cy, int cz, World world) {
         loadChunk(cx, cz, world);
     }
 
     @Override
-    public void unloadChunklet(int cx, int cy, int cz, World world) {
+    public synchronized void unloadChunklet(int cx, int cy, int cz, World world) {
         unloadChunk(cx, cz, world);
     }
 
     @Override
-    public void loadChunk(int cx, int cz, World world) {
+    public synchronized void loadChunk(int cx, int cz, World world) {
         if(world == null)
             return;
 
@@ -146,6 +149,10 @@ public class HashChunkManager implements ChunkManager {
 
         ChunkStore in = null;
 
+        File dataDir = new File(world.getWorldFolder(), "mcmmo_data");
+        if(dataDir.exists())
+            convertChunk(dataDir, cx, cz, world, true);
+
         try {
             in = readChunkStore(world, cx, cz);
         }
@@ -157,7 +164,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void unloadChunk(int cx, int cz, World world) {
+    public synchronized void unloadChunk(int cx, int cz, World world) {
         saveChunk(cx, cz, world);
 
         if(store.containsKey(world.getName() + "," + cx + "," + cz)) {
@@ -166,7 +173,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void saveChunk(int cx, int cz, World world) {
+    public synchronized void saveChunk(int cx, int cz, World world) {
         if(world == null)
             return;
 
@@ -181,7 +188,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public boolean isChunkLoaded(int cx, int cz, World world) {
+    public synchronized boolean isChunkLoaded(int cx, int cz, World world) {
         if(world == null)
             return false;
 
@@ -189,10 +196,10 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void chunkLoaded(int cx, int cz, World world) {}
+    public synchronized void chunkLoaded(int cx, int cz, World world) {}
 
     @Override
-    public void chunkUnloaded(int cx, int cz, World world) {
+    public synchronized void chunkUnloaded(int cx, int cz, World world) {
         if(world == null)
             return;
 
@@ -200,7 +207,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void saveWorld(World world) {
+    public synchronized void saveWorld(World world) {
         if(world == null)
             return;
 
@@ -226,7 +233,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void unloadWorld(World world) {
+    public synchronized void unloadWorld(World world) {
         if(world == null)
             return;
 
@@ -252,10 +259,10 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void loadWorld(World world) {}
+    public synchronized void loadWorld(World world) {}
 
     @Override
-    public void saveAll() {
+    public synchronized void saveAll() {
         closeAll();
 
         for(World world : Bukkit.getWorlds()) {
@@ -264,7 +271,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void unloadAll() {
+    public synchronized void unloadAll() {
         closeAll();
 
         for(World world : Bukkit.getWorlds()) {
@@ -273,7 +280,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public boolean isTrue(int x, int y, int z, World world) {
+    public synchronized boolean isTrue(int x, int y, int z, World world) {
         if(world == null)
             return false;
 
@@ -297,7 +304,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public boolean isTrue(Block block) {
+    public synchronized boolean isTrue(Block block) {
         if(block == null)
             return false;
 
@@ -305,7 +312,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void setTrue(int x, int y, int z, World world) {
+    public synchronized void setTrue(int x, int y, int z, World world) {
         if(world == null)
             return;
 
@@ -332,7 +339,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void setTrue(Block block) {
+    public synchronized void setTrue(Block block) {
         if(block == null)
             return;
 
@@ -340,7 +347,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void setFalse(int x, int y, int z, World world) {
+    public synchronized void setFalse(int x, int y, int z, World world) {
         if(world == null)
             return;
 
@@ -366,7 +373,7 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void setFalse(Block block) {
+    public synchronized void setFalse(Block block) {
         if(block == null)
             return;
 
@@ -374,91 +381,39 @@ public class HashChunkManager implements ChunkManager {
     }
 
     @Override
-    public void cleanUp() {}
-
-    public void convertChunk(File dataDir, int cx, int cz, World world) {
-        HashChunkletManager manager = new HashChunkletManager();
-        manager.loadChunk(cx, cz, world);
-
-        for(int y = 0; y < (world.getMaxHeight() / 64); y++) {
-            String chunkletName = world.getName() + "," + cx + "," + cz + "," + y;
-	    ChunkletStore tempChunklet = manager.store.get(chunkletName);
-            PrimitiveChunkletStore primitiveChunklet = null;
-            PrimitiveExChunkletStore primitiveExChunklet = null;
-            if(tempChunklet instanceof PrimitiveChunkletStore)
-                primitiveChunklet = (PrimitiveChunkletStore) tempChunklet;
-            else if(tempChunklet instanceof PrimitiveExChunkletStore)
-                primitiveExChunklet = (PrimitiveExChunkletStore) tempChunklet;
-            if(tempChunklet == null) {
-                continue;
-            } else {
-                String chunkName = world.getName() + "," + cx + "," + cz;
-                PrimitiveChunkStore cChunk = (PrimitiveChunkStore) store.get(chunkName);
-
-                if(cChunk != null) {
-                    int xPos = cx * 16;
-                    int zPos = cz * 16;
-
-                    for(int x = 0; x < 16; x++) {
-                        for(int z = 0; z < 16; z++) {
-                            int cxPos = xPos + x;
-                            int czPos = zPos + z;
-
-                            for(int y2 = (64 * y); y2 < (64 * y + 64); y2++) {
-                                if(!manager.isTrue(cxPos, y2, czPos, world))
-                                    continue;
-
-                                setTrue(cxPos, y2, czPos, world);
-                            }
-                        }
-                    }
-                    continue;
-                }
-
-                setTrue(cx * 16, 0, cz * 16, world);
-		setFalse(cx * 16, 0, cz * 16, world);
-                cChunk = (PrimitiveChunkStore) store.get(chunkName);
-
-                for(int x = 0; x < 16; x++) {
-                    for(int z = 0; z < 16; z++) {
-                        boolean[] oldArray;
-                        if(primitiveChunklet != null)
-                            oldArray = primitiveChunklet.store[x][z];
-                        if(primitiveExChunklet != null)
-                            oldArray = primitiveExChunklet.store[x][z];
-                        else
-                            return;
-                        boolean[] newArray = cChunk.store[x][z];
-                        if(oldArray.length < 64)
-                            return;
-                        else if(newArray.length < ((y * 64) + 64))
-                            return;
-                        System.arraycopy(oldArray, 0, newArray, (y * 64), 64);
-                    }
-                }
-            }
-        }
+    public synchronized void cleanUp() {}
 
-        manager.unloadChunk(cx, cz, world);
-        unloadChunk(cx, cz, world);
+    public synchronized void convertChunk(File dataDir, int cx, int cz, World world) {
+        convertChunk(dataDir, cx, cz, world, false);
+    }
 
+    public synchronized void convertChunk(File dataDir, int cx, int cz, World world, boolean actually) {
+        if(!actually)
+            return;
+        if(!dataDir.exists()) return;
         File cxDir = new File(dataDir, "" + cx);
         if(!cxDir.exists()) return;
         File czDir = new File(cxDir, "" + cz);
         if(!czDir.exists()) return;
 
-        for(File yFile : czDir.listFiles()) {
-            if(!yFile.exists())
+        boolean conversionSet = false;
+
+        for(BlockStoreConversionZDirectory converter : this.converters) {
+            if(converter == null)
                 continue;
 
-            yFile.delete();
+            if(converter.taskID >= 0)
+                continue;
+
+            converter.start(world, cxDir, czDir);
+            conversionSet = true;
+            break;
         }
 
-        if(czDir.listFiles().length <= 0)
-            czDir.delete();
-        if(cxDir.listFiles().length <= 0)
-            cxDir.delete();
-        if(dataDir.listFiles().length <= 0)
-            dataDir.delete();
+        if(!conversionSet) {
+            BlockStoreConversionZDirectory converter = new BlockStoreConversionZDirectory();
+            converter.start(world, cxDir, czDir);
+            converters.add(converter);
+        }
     }
 }

+ 12 - 12
src/main/java/org/getspout/spoutapi/chunkstore/mcMMOSimpleRegionFile.java

@@ -102,7 +102,7 @@ public class mcMMOSimpleRegionFile {
 		}
 	}
 
-	public final RandomAccessFile getFile() {
+	public synchronized final RandomAccessFile getFile() {
 		lastAccessTime = System.currentTimeMillis();
 		if (file == null) {
 			try {
@@ -150,7 +150,7 @@ public class mcMMOSimpleRegionFile {
 		return file;
 	}
 
-	public boolean testCloseTimeout() {
+	public synchronized boolean testCloseTimeout() {
 		/*if (System.currentTimeMillis() - TIMEOUT_TIME > lastAccessTime) {
 			close();
 			return true;
@@ -158,12 +158,12 @@ public class mcMMOSimpleRegionFile {
 		return false;
 	}
 
-	public DataOutputStream getOutputStream(int x, int z) {
+	public synchronized DataOutputStream getOutputStream(int x, int z) {
 		int index = getChunkIndex(x, z);
 		return new DataOutputStream(new DeflaterOutputStream(new mcMMOSimpleChunkBuffer(this, index)));
 	}
 
-	public DataInputStream getInputStream(int x, int z) throws IOException {
+	public synchronized DataInputStream getInputStream(int x, int z) throws IOException {
 		int index = getChunkIndex(x, z);
 		int actualLength = dataActualLength[index];
 		if (actualLength == 0) {
@@ -176,7 +176,7 @@ public class mcMMOSimpleRegionFile {
 		return new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(data)));
 	}
 
-	void write(int index, byte[] buffer, int size) throws IOException {
+	synchronized void write(int index, byte[] buffer, int size) throws IOException {
 		int oldStart = setInUse(index, false);
 		int start = findSpace(oldStart, size);
 		getFile().seek(start << segmentSize);
@@ -188,7 +188,7 @@ public class mcMMOSimpleRegionFile {
 		saveFAT();
 	}
 
-	public void close() {
+	public synchronized void close() {
 		try {
 			if (file != null) {
 				file.seek(4096 * 2);
@@ -200,7 +200,7 @@ public class mcMMOSimpleRegionFile {
 		}
 	}
 
-	private int setInUse(int index, boolean used) {
+	private synchronized int setInUse(int index, boolean used) {
 		if (dataActualLength[index] == 0) {
 			return dataStart[index];
 		}
@@ -225,7 +225,7 @@ public class mcMMOSimpleRegionFile {
 		return dataStart[index];
 	}
 
-	private void extendFile() throws IOException {
+	private synchronized void extendFile() throws IOException {
 		long extend = (-getFile().length()) & segmentMask;
 
 		getFile().seek(getFile().length());
@@ -235,7 +235,7 @@ public class mcMMOSimpleRegionFile {
 		}
 	}
 
-	private int findSpace(int oldStart, int size) {
+	private synchronized int findSpace(int oldStart, int size) {
 		int segments = sizeToSegments(size);
 
 		boolean oldFree = true;
@@ -268,7 +268,7 @@ public class mcMMOSimpleRegionFile {
 		return start;
 	}
 
-	private int sizeToSegments(int size) {
+	private synchronized int sizeToSegments(int size) {
 		if (size <= 0) {
 			return 1;
 		} else {
@@ -276,7 +276,7 @@ public class mcMMOSimpleRegionFile {
 		}
 	}
 
-	private Integer getChunkIndex(int x, int z) {
+	private synchronized Integer getChunkIndex(int x, int z) {
 		if (rx != (x >> 5) || rz != (z >> 5)) {
 			throw new RuntimeException(x + ", " + z + " not in region " + rx + ", " + rz);
 		}
@@ -287,7 +287,7 @@ public class mcMMOSimpleRegionFile {
 		return (x << 5) + z;
 	}
 
-	private void saveFAT() throws IOException {
+	private synchronized void saveFAT() throws IOException {
 		getFile().seek(0);
 		for (int i = 0; i < 1024; i++) {
 			getFile().writeInt(dataStart[i]);

+ 1 - 1
src/main/resources/hidden.yml

@@ -6,4 +6,4 @@ Options:
     # true to use Chunklets metadata store system, false to disable
     Chunklets: true
     # Square root of the number of chunks to convert per tick.
-    ConversionRate: 3
+    ConversionRate: 1