java - 为文件存储预分配驱动器空间

标签 java database vfs

是否有一种 Java 方法可以预分配驱动器空间供应用程序独占使用?

没有要求这个空间是一个单独的文件系统或现有文件系统的一部分(因此可以很容易地成为一个数据库),但它应该允许保留指定的空间量并允许随机读/写具有高足够的吞吐量。

最佳答案

这是我基于 JNA 的 fallocate 解决方案的精简版。主要技巧是获取 native 文件描述符。到目前为止,我只在 Linux 上测试过它,但它应该适用于所有现代 POSIX/非 Windows 系统。在 Windows 上没有必要,因为默认情况下 Windows 不会创建稀疏文件(仅使用 StandardOpenOption.SPARSE),所以 RandomAccessFile.setLength(size)FileChannel。 write(ByteBuffer.allocate(1), size - 1) 就足够了。

/**
 * Provides access to operating system-specific {@code fallocate} and
 * {@code posix_fallocate} functions.
 */
public final class Fallocate {

    private static final boolean IS_LINUX = Platform.isLinux();
    private static final boolean IS_POSIX = !Platform.isWindows();

    private static final int FALLOC_FL_KEEP_SIZE = 0x01;

    private final int fd;
    private int mode;
    private long offset;
    private final long length;

    private Fallocate(int fd, long length) {
        if (!isSupported()) {
            throwUnsupported("fallocate");
        }
        this.fd = fd;
        this.length = length;
    }

    public static boolean isSupported() {
        return IS_POSIX;
    }

    public static Fallocate forChannel(FileChannel channel, long length) {
        return new Fallocate(getDescriptor(channel), length);
    }

    public static Fallocate forDescriptor(FileDescriptor descriptor, long length) {
        return new Fallocate(getDescriptor(descriptor), length);
    }

    public Fallocate fromOffset(long offset) {
        this.offset = offset;
        return this;
    }

    public Fallocate keepSize() {
        requireLinux("fallocate keep size");
        mode |= FALLOC_FL_KEEP_SIZE;
        return this;
    }

    private void requireLinux(String feature) {
        if (!IS_LINUX) {
            throwUnsupported(feature);
        }
    }

    private void throwUnsupported(String feature) {
        throw new UnsupportedOperationException(feature +
                " is not supported on this operating system");
    }

    public void execute() throws IOException {
        final int errno;
        if (IS_LINUX) {
            final int result = FallocateHolder.fallocate(fd, mode, offset, length);
            errno = result == 0 ? 0 : Native.getLastError();
        } else {
            errno = PosixFallocateHolder.posix_fallocate(fd, offset, length);
        }
        if (errno != 0) {
            throw new IOException("fallocate returned " + errno);
        }
    }

    private static class FallocateHolder {

        static {
            Native.register(Platform.C_LIBRARY_NAME);
        }

        private static native int fallocate(int fd, int mode, long offset, long length);
    }

    private static class PosixFallocateHolder {

        static {
            Native.register(Platform.C_LIBRARY_NAME);
        }

        private static native int posix_fallocate(int fd, long offset, long length);
    }

    private static int getDescriptor(FileChannel channel) {
        try {
            // sun.nio.ch.FileChannelImpl declares private final java.io.FileDescriptor fd
            final Field field = channel.getClass().getDeclaredField("fd");
            field.setAccessible(true);
            return getDescriptor((FileDescriptor) field.get(channel));
        } catch (final Exception e) {
            throw new UnsupportedOperationException("unsupported FileChannel implementation", e);
        }
    }

    private static int getDescriptor(FileDescriptor descriptor) {
        try {
            // Oracle java.io.FileDescriptor declares private int fd
            final Field field = descriptor.getClass().getDeclaredField("fd");
            field.setAccessible(true);
            return (int) field.get(descriptor);
        } catch (final Exception e) {
            throw new UnsupportedOperationException("unsupported FileDescriptor implementation", e);
        }
    }
}

关于java - 为文件存储预分配驱动器空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18031841/

相关文章:

mysql - 数据库设计不支持产品录入。

mysql - 3 个 SQL 语句的问题

groovy - 无法使用Gradle中的Groovy VFS库下载文件

java - 证书异常 : No subject alternative names present

sql - 使用此 SQL 语句检测到死锁?

java - Hibernate事务异常: nested transactions not supported

maven - 创建maven项目失败: '.../pom.xml' already exists in VFS (IntelliJ)

java - 任何免费的 Java VFS 库?

java - Android 从隐式 Intent 中获取 .txt 文件

java - 轴类CasException