/** * Finds the multichunks that need to be downloaded for the given file version -- using the local * database and given winners database. Returns a set of multichunk identifiers. */ private Collection<MultiChunkId> determineMultiChunksToDownload( FileVersion fileVersion, MemoryDatabase winnersDatabase) { Set<MultiChunkId> multiChunksToDownload = new HashSet<MultiChunkId>(); // First: Check if we know this file locally! List<MultiChunkId> multiChunkIds = localDatabase.getMultiChunkIds(fileVersion.getChecksum()); if (multiChunkIds.size() > 0) { multiChunksToDownload.addAll(multiChunkIds); } else { // Second: We don't know it locally; must be from the winners database FileContent winningFileContent = winnersDatabase.getContent(fileVersion.getChecksum()); boolean winningFileHasContent = winningFileContent != null; if (winningFileHasContent) { // File can be empty! List<ChunkChecksum> fileChunks = winningFileContent.getChunks(); // TODO [medium] Instead of just looking for multichunks to download here, we should look // for chunks in local files as well // and return the chunk positions in the local files ChunkPosition (chunk123 at file12, // offset 200, size 250) Map<ChunkChecksum, MultiChunkId> checksumsWithMultiChunkIds = localDatabase.getMultiChunkIdsByChecksums(fileChunks); for (ChunkChecksum chunkChecksum : fileChunks) { MultiChunkId multiChunkIdForChunk = checksumsWithMultiChunkIds.get(chunkChecksum); if (multiChunkIdForChunk == null) { multiChunkIdForChunk = winnersDatabase.getMultiChunkIdForChunk(chunkChecksum); if (multiChunkIdForChunk == null) { throw new RuntimeException("Cannot find multichunk for chunk " + chunkChecksum); } } if (!multiChunksToDownload.contains(multiChunkIdForChunk)) { logger.log( Level.INFO, " + Adding multichunk " + multiChunkIdForChunk + " to download list ..."); multiChunksToDownload.add(multiChunkIdForChunk); } } } } return multiChunksToDownload; }