geforkt von Mirrors/FastAsyncWorldEdit
feat: improvements to clipboard on disk (#2162)
* feat: improvements to clipboard on disk - close clipboard on instantiation failure - set canHaveBiomes when loading clipboard from disk (only possible cause I can find for #2151 ..?) - check file length and give more appropriate error if it exceeds maximum. Fixes #2151 I guess?# - set byteBuffer to null before invoking cleaning. Addresses #1985 - don't catch and print all exceptions when getBlock fails - prevents large console output for what is likely to be a failed operation anyway * Fix comments
Dieser Commit ist enthalten in:
Ursprung
d82bf0527e
Commit
508b94ddc3
@ -64,9 +64,9 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
private final int headerSize;
|
private final int headerSize;
|
||||||
|
|
||||||
private RandomAccessFile braf;
|
private RandomAccessFile braf;
|
||||||
private MappedByteBuffer byteBuffer;
|
private MappedByteBuffer byteBuffer = null;
|
||||||
|
|
||||||
private FileChannel fileChannel;
|
private FileChannel fileChannel = null;
|
||||||
private boolean hasBiomes = false;
|
private boolean hasBiomes = false;
|
||||||
private boolean canHaveBiomes = true;
|
private boolean canHaveBiomes = true;
|
||||||
private int nbtBytesRemaining;
|
private int nbtBytesRemaining;
|
||||||
@ -133,7 +133,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
this.braf = new RandomAccessFile(file, "rw");
|
this.braf = new RandomAccessFile(file, "rw");
|
||||||
long fileLength = (long) getVolume() * 2L + (long) headerSize;
|
long fileLength = (long) (getVolume() << 1) + (long) headerSize;
|
||||||
braf.setLength(0);
|
braf.setLength(0);
|
||||||
braf.setLength(fileLength);
|
braf.setLength(fileLength);
|
||||||
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) fileLength;
|
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) fileLength;
|
||||||
@ -144,7 +144,11 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
byteBuffer.putChar(6, (char) getHeight());
|
byteBuffer.putChar(6, (char) getHeight());
|
||||||
byteBuffer.putChar(8, (char) getLength());
|
byteBuffer.putChar(8, (char) getLength());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
close();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
close();
|
||||||
|
throw t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,11 +173,15 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
nbtMap = new HashMap<>();
|
nbtMap = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
checkFileLength(file);
|
||||||
this.braf = new RandomAccessFile(file, "rw");
|
this.braf = new RandomAccessFile(file, "rw");
|
||||||
braf.setLength(file.length());
|
braf.setLength(file.length());
|
||||||
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) file.length();
|
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) file.length();
|
||||||
init();
|
init();
|
||||||
long biomeLength = (long) ((getHeight() >> 2) + 1) * ((getLength() >> 2) + 1) * ((getWidth() >> 2) + 1);
|
|
||||||
|
int biomeLength = ((getHeight() >> 2) + 1) * ((getLength() >> 2) + 1) * ((getWidth() >> 2) + 1);
|
||||||
|
canHaveBiomes = (long) headerSize + biomeLength < Integer.MAX_VALUE;
|
||||||
|
|
||||||
if (headerSize >= VERSION_2_HEADER_SIZE) {
|
if (headerSize >= VERSION_2_HEADER_SIZE) {
|
||||||
readBiomeStatusFromHeader();
|
readBiomeStatusFromHeader();
|
||||||
int nbtCount = readNBTSavedCountFromHeader();
|
int nbtCount = readNBTSavedCountFromHeader();
|
||||||
@ -181,12 +189,42 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
if (Settings.settings().CLIPBOARD.SAVE_CLIPBOARD_NBT_TO_DISK && (nbtCount + entitiesCount > 0)) {
|
if (Settings.settings().CLIPBOARD.SAVE_CLIPBOARD_NBT_TO_DISK && (nbtCount + entitiesCount > 0)) {
|
||||||
loadNBTFromFileFooter(nbtCount, entitiesCount, biomeLength);
|
loadNBTFromFileFooter(nbtCount, entitiesCount, biomeLength);
|
||||||
}
|
}
|
||||||
} else if (braf.length() - headerSize == ((long) getVolume() << 1) + biomeLength) {
|
} else if (canHaveBiomes && braf.length() - headerSize == ((long) getVolume() << 1) + biomeLength) {
|
||||||
hasBiomes = true;
|
hasBiomes = true;
|
||||||
}
|
}
|
||||||
getAndSetOffsetAndOrigin();
|
getAndSetOffsetAndOrigin();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
close();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
close();
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkFileLength(File file) throws IOException {
|
||||||
|
long expectedFileSize = headerSize + ((long) getVolume() << 1);
|
||||||
|
if (file.length() > Integer.MAX_VALUE) {
|
||||||
|
if (expectedFileSize >= Integer.MAX_VALUE) {
|
||||||
|
throw new IOException(String.format(
|
||||||
|
"Cannot load clipboard of file size: %d > 2147483647 bytes (2.147 GiB), " + "volume: %d blocks",
|
||||||
|
file.length(),
|
||||||
|
getVolume()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
throw new IOException(String.format(
|
||||||
|
"Cannot load clipboard of file size > 2147483647 bytes (2.147 GiB). Possible corrupt file? Mismatch" +
|
||||||
|
" between volume `%d` and file length `%d`!",
|
||||||
|
file.length(),
|
||||||
|
getVolume()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else if (expectedFileSize != file.length()) {
|
||||||
|
throw new IOException(String.format(
|
||||||
|
"Possible corrupt clipboard file? Mismatch between expected file size `%d` and actual file size `%d`!",
|
||||||
|
expectedFileSize,
|
||||||
|
file.length()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,13 +524,26 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
fileChannel.close();
|
fileChannel.close();
|
||||||
braf.close();
|
braf.close();
|
||||||
file.setWritable(true);
|
file.setWritable(true);
|
||||||
closeDirectBuffer(byteBuffer);
|
MappedByteBuffer tmpBuffer = byteBuffer;
|
||||||
byteBuffer = null;
|
byteBuffer = null;
|
||||||
|
closeDirectBuffer(tmpBuffer);
|
||||||
fileChannel = null;
|
fileChannel = null;
|
||||||
braf = null;
|
braf = null;
|
||||||
|
} else if (fileChannel != null) {
|
||||||
|
fileChannel.close();
|
||||||
|
fileChannel = null;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
if (fileChannel != null) {
|
||||||
|
try {
|
||||||
|
fileChannel.close();
|
||||||
|
fileChannel = null;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.error("Could not close file channel on clipboard {}. If this belongs to a player, the server may " +
|
||||||
|
"need to be restarted for clipboard use to work.", getFile().getName(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,8 +699,6 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
char ordinal = byteBuffer.getChar(diskIndex);
|
char ordinal = byteBuffer.getChar(diskIndex);
|
||||||
return BlockState.getFromOrdinal(ordinal);
|
return BlockState.getFromOrdinal(ordinal);
|
||||||
} catch (IndexOutOfBoundsException ignored) {
|
} catch (IndexOutOfBoundsException ignored) {
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return BlockTypes.AIR.getDefaultState();
|
return BlockTypes.AIR.getDefaultState();
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren