Esempio n. 1
0
  private void handleGetFileRequest(GetFileRequest fileRequest) {
    try {
      FileHistoryId fileHistoryId = FileHistoryId.parseFileId(fileRequest.getFileHistoryId());
      long version = fileRequest.getVersion();

      FileVersion fileVersion = localDatabase.getFileVersion(fileHistoryId, version);
      FileContent fileContent = localDatabase.getFileContent(fileVersion.getChecksum(), true);
      Map<ChunkChecksum, MultiChunkId> multiChunks =
          localDatabase.getMultiChunkIdsByChecksums(fileContent.getChunks());

      TransferManager transferManager =
          config.getTransferPlugin().createTransferManager(config.getConnection());
      Downloader downloader = new Downloader(config, transferManager);
      Assembler assembler = new Assembler(config, localDatabase);

      downloader.downloadAndDecryptMultiChunks(new HashSet<MultiChunkId>(multiChunks.values()));

      File tempFile = assembler.assembleToCache(fileVersion);
      String tempFileToken = StringUtil.toHex(ObjectId.secureRandomBytes(40));

      GetFileResponse fileResponse =
          new GetFileResponse(fileRequest.getId(), fileRequest.getRoot(), tempFileToken);
      GetFileResponseInternal fileResponseInternal =
          new GetFileResponseInternal(fileResponse, tempFile);

      eventBus.post(fileResponseInternal);
    } catch (Exception e) {
      logger.log(Level.WARNING, "Cannot reassemble file.", e);
      eventBus.post(new BadRequestResponse(fileRequest.getId(), "Cannot reassemble file."));
    }
  }
  /**
   * 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;
  }
Esempio n. 3
0
  private void handleGetFileHistoryRequest(GetFileHistoryRequest fileHistoryRequest) {
    FileHistoryId fileHistoryId = FileHistoryId.parseFileId(fileHistoryRequest.getFileHistoryId());
    List<FileVersion> fileHistory = localDatabase.getFileHistory(fileHistoryId);
    GetFileHistoryResponse fileHistoryRespose =
        new GetFileHistoryResponse(
            fileHistoryRequest.getId(), fileHistoryRequest.getRoot(), fileHistory);

    eventBus.post(fileHistoryRespose);
  }
Esempio n. 4
0
  private void handleGetDatabaseVersionHeadersRequest(
      GetDatabaseVersionHeadersRequest headersRequest) {
    List<DatabaseVersionHeader> databaseVersionHeaders =
        localDatabase.getNonEmptyDatabaseVersionHeaders();
    GetDatabaseVersionHeadersResponse headersResponse =
        new GetDatabaseVersionHeadersResponse(
            headersRequest.getId(), headersRequest.getRoot(), databaseVersionHeaders);

    eventBus.post(headersResponse);
  }
Esempio n. 5
0
  /**
   * This method implements the index/deduplication functionality of Syncany. It uses a {@link
   * Deduper} to break files down, compares them to the local database and creates a new {@link
   * DatabaseVersion} as a result.
   *
   * <p>Depending on what has changed, the new database version will contain new instances of {@link
   * PartialFileHistory}, {@link FileVersion}, {@link FileContent}, {@link ChunkEntry} and {@link
   * MultiChunkEntry}.
   *
   * @param files List of files to be deduplicated
   * @return New database version containing new/changed/deleted entities
   * @throws IOException If the chunking/deduplication cannot read/process any of the files
   */
  public DatabaseVersion index(List<File> files) throws IOException {
    DatabaseVersion newDatabaseVersion = new DatabaseVersion();

    // Load file history cache
    List<PartialFileHistory> fileHistoriesWithLastVersion =
        localDatabase.getFileHistoriesWithLastVersion();

    // TODO [medium] This should be in FileHistoryDao
    Map<FileChecksum, List<PartialFileHistory>> fileChecksumCache =
        fillFileChecksumCache(fileHistoriesWithLastVersion);
    Map<String, PartialFileHistory> filePathCache = fillFilePathCache(fileHistoriesWithLastVersion);

    // Find and index new files
    deduper.deduplicate(
        files,
        new IndexerDeduperListener(newDatabaseVersion, fileChecksumCache, filePathCache, listener));

    // Find and remove deleted files
    removeDeletedFiles(newDatabaseVersion, fileHistoriesWithLastVersion);

    return newDatabaseVersion;
  }
Esempio n. 6
0
  private void handleGetFileTreeRequest(GetFileTreeRequest fileTreeRequest) {
    try {
      String prefixLikeQuery = fileTreeRequest.getPrefix() + "%";
      Date date =
          (fileTreeRequest.getDate() != null)
              ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").parse(fileTreeRequest.getDate())
              : null;

      Map<String, FileVersion> fileTree =
          localDatabase.getFileTree(prefixLikeQuery, date, false, (FileType[]) null);
      GetFileTreeResponse fileTreeResponse =
          new GetFileTreeResponse(
              fileTreeRequest.getId(),
              fileTreeRequest.getRoot(),
              fileTreeRequest.getPrefix(),
              new ArrayList<FileVersion>(fileTree.values()));

      eventBus.post(fileTreeResponse);
    } catch (Exception e) {
      eventBus.post(
          new BadRequestResponse(fileTreeRequest.getId(), "Invalid request: " + e.getMessage()));
    }
  }