DownloadQueue.java

net.minecraft.server.packs.DownloadQueue

信息

  • 全限定名:net.minecraft.server.packs.DownloadQueue
  • 类型:public class
  • 包:net.minecraft.server.packs
  • 源码路径:src/main/java/net/minecraft/server/packs/DownloadQueue.java
  • 起始行号:L32
  • 实现:AutoCloseable
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • MAX_KEPT_PACKS

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L34
    • 说明:

      TODO

  • cacheDir

    • 类型: Path
    • 修饰符: private final
    • 源码定位: L35
    • 说明:

      TODO

  • eventLog

    • 类型: JsonEventLog<DownloadQueue.LogEntry>
    • 修饰符: private final
    • 源码定位: L36
    • 说明:

      TODO

  • tasks

    • 类型: ConsecutiveExecutor
    • 修饰符: private final
    • 源码定位: L37
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.packs.DownloadQueue.BatchConfig

    • 类型: record
    • 修饰符: public
    • 源码定位: L103
    • 说明:

      TODO

  • net.minecraft.server.packs.DownloadQueue.BatchResult

    • 类型: record
    • 修饰符: public
    • 源码定位: L106
    • 说明:

      TODO

  • net.minecraft.server.packs.DownloadQueue.DownloadRequest

    • 类型: record
    • 修饰符: public
    • 源码定位: L112
    • 说明:

      TODO

  • net.minecraft.server.packs.DownloadQueue.FileInfoEntry

    • 类型: record
    • 修饰符: private
    • 源码定位: L115
    • 说明:

      TODO

  • net.minecraft.server.packs.DownloadQueue.LogEntry

    • 类型: record
    • 修饰符: private
    • 源码定位: L125
    • 说明:

      TODO

构造器

public DownloadQueue(Path cacheDir) @ L39

  • 构造器名:DownloadQueue
  • 源码定位:L39
  • 修饰符:public

参数:

  • cacheDir: Path

说明:

TODO

方法

下面的方法块按源码顺序生成。

private DownloadQueue.BatchResult runDownload(DownloadQueue.BatchConfig config, Map<UUID,DownloadQueue.DownloadRequest> requests) @ L46

  • 方法名:runDownload
  • 源码定位:L46
  • 返回类型:DownloadQueue.BatchResult
  • 修饰符:private

参数:

  • config: DownloadQueue.BatchConfig
  • requests: Map<UUID,DownloadQueue.DownloadRequest>

说明:

TODO

private Either<String,DownloadQueue.FileInfoEntry> getFileInfo(Path downloadedFile) @ L82

  • 方法名:getFileInfo
  • 源码定位:L82
  • 返回类型:Either<String,DownloadQueue.FileInfoEntry>
  • 修饰符:private

参数:

  • downloadedFile: Path

说明:

TODO

public CompletableFuture<DownloadQueue.BatchResult> downloadBatch(DownloadQueue.BatchConfig config, Map<UUID,DownloadQueue.DownloadRequest> requests) @ L93

  • 方法名:downloadBatch
  • 源码定位:L93
  • 返回类型:CompletableFuture<DownloadQueue.BatchResult>
  • 修饰符:public

参数:

  • config: DownloadQueue.BatchConfig
  • requests: Map<UUID,DownloadQueue.DownloadRequest>

说明:

TODO

public void close() @ L97

  • 方法名:close
  • 源码定位:L97
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

代码

public class DownloadQueue implements AutoCloseable {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final int MAX_KEPT_PACKS = 20;
    private final Path cacheDir;
    private final JsonEventLog<DownloadQueue.LogEntry> eventLog;
    private final ConsecutiveExecutor tasks = new ConsecutiveExecutor(Util.nonCriticalIoPool(), "download-queue");
 
    public DownloadQueue(Path cacheDir) throws IOException {
        this.cacheDir = cacheDir;
        FileUtil.createDirectoriesSafe(cacheDir);
        this.eventLog = JsonEventLog.open(DownloadQueue.LogEntry.CODEC, cacheDir.resolve("log.json"));
        DownloadCacheCleaner.vacuumCacheDir(cacheDir, 20);
    }
 
    private DownloadQueue.BatchResult runDownload(DownloadQueue.BatchConfig config, Map<UUID, DownloadQueue.DownloadRequest> requests) {
        DownloadQueue.BatchResult result = new DownloadQueue.BatchResult();
        requests.forEach(
            (id, request) -> {
                Path targetDir = this.cacheDir.resolve(id.toString());
                Path downloadedFile = null;
 
                try {
                    downloadedFile = HttpUtil.downloadFile(
                        targetDir, request.url, config.headers, config.hashFunction, request.hash, config.maxSize, config.proxy, config.listener
                    );
                    result.downloaded.put(id, downloadedFile);
                } catch (Exception var9) {
                    LOGGER.error("Failed to download {}", request.url, var9);
                    result.failed.add(id);
                }
 
                try {
                    this.eventLog
                        .write(
                            new DownloadQueue.LogEntry(
                                id,
                                request.url.toString(),
                                Instant.now(),
                                Optional.ofNullable(request.hash).map(HashCode::toString),
                                downloadedFile != null ? this.getFileInfo(downloadedFile) : Either.left("download_failed")
                            )
                        );
                } catch (Exception var8) {
                    LOGGER.error("Failed to log download of {}", request.url, var8);
                }
            }
        );
        return result;
    }
 
    private Either<String, DownloadQueue.FileInfoEntry> getFileInfo(Path downloadedFile) {
        try {
            long size = Files.size(downloadedFile);
            Path relativePath = this.cacheDir.relativize(downloadedFile);
            return Either.right(new DownloadQueue.FileInfoEntry(relativePath.toString(), size));
        } catch (IOException var5) {
            LOGGER.error("Failed to get file size of {}", downloadedFile, var5);
            return Either.left("no_access");
        }
    }
 
    public CompletableFuture<DownloadQueue.BatchResult> downloadBatch(DownloadQueue.BatchConfig config, Map<UUID, DownloadQueue.DownloadRequest> requests) {
        return CompletableFuture.supplyAsync(() -> this.runDownload(config, requests), this.tasks::schedule);
    }
 
    @Override
    public void close() throws IOException {
        this.tasks.close();
        this.eventLog.close();
    }
 
    public record BatchConfig(HashFunction hashFunction, int maxSize, Map<String, String> headers, Proxy proxy, HttpUtil.DownloadProgressListener listener) {
    }
 
    public record BatchResult(Map<UUID, Path> downloaded, Set<UUID> failed) {
        public BatchResult() {
            this(new HashMap<>(), new HashSet<>());
        }
    }
 
    public record DownloadRequest(URL url, @Nullable HashCode hash) {
    }
 
    private record FileInfoEntry(String name, long size) {
        public static final Codec<DownloadQueue.FileInfoEntry> CODEC = RecordCodecBuilder.create(
            i -> i.group(
                    Codec.STRING.fieldOf("name").forGetter(DownloadQueue.FileInfoEntry::name),
                    Codec.LONG.fieldOf("size").forGetter(DownloadQueue.FileInfoEntry::size)
                )
                .apply(i, DownloadQueue.FileInfoEntry::new)
        );
    }
 
    private record LogEntry(UUID id, String url, Instant time, Optional<String> hash, Either<String, DownloadQueue.FileInfoEntry> errorOrFileInfo) {
        public static final Codec<DownloadQueue.LogEntry> CODEC = RecordCodecBuilder.create(
            i -> i.group(
                    UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(DownloadQueue.LogEntry::id),
                    Codec.STRING.fieldOf("url").forGetter(DownloadQueue.LogEntry::url),
                    ExtraCodecs.INSTANT_ISO8601.fieldOf("time").forGetter(DownloadQueue.LogEntry::time),
                    Codec.STRING.optionalFieldOf("hash").forGetter(DownloadQueue.LogEntry::hash),
                    Codec.mapEither(Codec.STRING.fieldOf("error"), DownloadQueue.FileInfoEntry.CODEC.fieldOf("file"))
                        .forGetter(DownloadQueue.LogEntry::errorOrFileInfo)
                )
                .apply(i, DownloadQueue.LogEntry::new)
        );
    }
}

引用的其他类

  • DownloadCacheCleaner

    • 引用位置: 方法调用
    • 关联成员: DownloadCacheCleaner.vacuumCacheDir()
  • FileUtil

    • 引用位置: 方法调用
    • 关联成员: FileUtil.createDirectoriesSafe()
  • HttpUtil

    • 引用位置: 方法调用
    • 关联成员: HttpUtil.downloadFile()
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.nonCriticalIoPool()
  • JsonEventLog

    • 引用位置: 字段/方法调用
    • 关联成员: JsonEventLog.open()
  • ConsecutiveExecutor

    • 引用位置: 字段/构造调用
    • 关联成员: ConsecutiveExecutor()