Search in sources :

Example 16 with MultiChunkId

use of org.syncany.database.MultiChunkEntry.MultiChunkId in project syncany by syncany.

the class MultiChunkSqlDao method createMultiChunkEntriesWithChunks.

private Map<MultiChunkId, MultiChunkEntry> createMultiChunkEntriesWithChunks(ResultSet resultSet) throws SQLException {
    Map<MultiChunkId, MultiChunkEntry> multiChunkEntries = new HashMap<MultiChunkId, MultiChunkEntry>();
    MultiChunkId currentMultiChunkId = null;
    while (resultSet.next()) {
        MultiChunkId multiChunkId = MultiChunkId.parseMultiChunkId(resultSet.getString("multichunk_id"));
        long multiChunkSize = resultSet.getLong("size");
        MultiChunkEntry multiChunkEntry = null;
        if (currentMultiChunkId != null && currentMultiChunkId.equals(multiChunkId)) {
            multiChunkEntry = multiChunkEntries.get(multiChunkId);
        } else {
            multiChunkEntry = new MultiChunkEntry(multiChunkId, multiChunkSize);
        }
        multiChunkEntry.addChunk(ChunkChecksum.parseChunkChecksum(resultSet.getString("chunk_checksum")));
        multiChunkEntries.put(multiChunkId, multiChunkEntry);
        currentMultiChunkId = multiChunkId;
    }
    return multiChunkEntries;
}
Also used : MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) HashMap(java.util.HashMap) MultiChunkEntry(org.syncany.database.MultiChunkEntry)

Example 17 with MultiChunkId

use of org.syncany.database.MultiChunkEntry.MultiChunkId in project syncany by syncany.

the class Downloader method downloadAndDecryptMultiChunks.

/** 
	 * Downloads the given multichunks from the remote storage and decrypts them
	 * to the local cache folder. 
	 */
public void downloadAndDecryptMultiChunks(Set<MultiChunkId> unknownMultiChunkIds) throws StorageException, IOException {
    logger.log(Level.INFO, "Downloading and extracting multichunks ...");
    int multiChunkNumber = 0;
    for (MultiChunkId multiChunkId : unknownMultiChunkIds) {
        File localEncryptedMultiChunkFile = config.getCache().getEncryptedMultiChunkFile(multiChunkId);
        File localDecryptedMultiChunkFile = config.getCache().getDecryptedMultiChunkFile(multiChunkId);
        MultichunkRemoteFile remoteMultiChunkFile = new MultichunkRemoteFile(multiChunkId);
        multiChunkNumber++;
        if (localDecryptedMultiChunkFile.exists()) {
            logger.log(Level.INFO, "  + Decrypted multichunk exists locally " + multiChunkId + ". No need to download it!");
        } else {
            eventBus.post(new DownDownloadFileSyncExternalEvent(config.getLocalDir().getAbsolutePath(), "multichunk", multiChunkNumber, unknownMultiChunkIds.size()));
            logger.log(Level.INFO, "  + Downloading multichunk " + multiChunkId + " ...");
            transferManager.download(remoteMultiChunkFile, localEncryptedMultiChunkFile);
            try {
                logger.log(Level.INFO, "  + Decrypting multichunk " + multiChunkId + " ...");
                InputStream multiChunkInputStream = config.getTransformer().createInputStream(new FileInputStream(localEncryptedMultiChunkFile));
                OutputStream decryptedMultiChunkOutputStream = new FileOutputStream(localDecryptedMultiChunkFile);
                IOUtils.copy(multiChunkInputStream, decryptedMultiChunkOutputStream);
                decryptedMultiChunkOutputStream.close();
                multiChunkInputStream.close();
            } catch (IOException e) {
                // Security: Deleting the multichunk if the decryption/extraction failed is important!
                //           If it is not deleted, the partially decrypted multichunk will reside in the
                //           local cache and the next 'down' will try to use it. If this is the only
                //           multichunk that has been tampered with, other changes might be applied to the 
                //           file system! See https://github.com/syncany/syncany/issues/59#issuecomment-55154793
                logger.log(Level.FINE, "    -> FAILED: Decryption/extraction of multichunk failed, deleting " + multiChunkId + " ...");
                localDecryptedMultiChunkFile.delete();
                throw new IOException("Decryption/extraction of multichunk " + multiChunkId + " failed. The multichunk might have been tampered with!", e);
            } finally {
                logger.log(Level.FINE, "  + Locally deleting multichunk " + multiChunkId + " ...");
                localEncryptedMultiChunkFile.delete();
            }
        }
    }
    transferManager.disconnect();
}
Also used : DownDownloadFileSyncExternalEvent(org.syncany.operations.daemon.messages.DownDownloadFileSyncExternalEvent) MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) File(java.io.File) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile) FileInputStream(java.io.FileInputStream)

Example 18 with MultiChunkId

use of org.syncany.database.MultiChunkEntry.MultiChunkId in project syncany by syncany.

the class UpOperation method addMultiChunksToTransaction.

/**
	 * This methods adds the multichunks that are not yet present in the remote repo to the {@link RemoteTransaction} for
	 * uploading. Multichunks are not uploaded if they are dirty.
	 *
	 * @param multiChunkEntries Collection of multiChunkEntries that are included in the new {@link DatabaseVersion}
	 */
private void addMultiChunksToTransaction(RemoteTransaction remoteTransaction, Collection<MultiChunkEntry> multiChunksEntries) throws InterruptedException, StorageException {
    List<MultiChunkId> dirtyMultiChunkIds = localDatabase.getDirtyMultiChunkIds();
    for (MultiChunkEntry multiChunkEntry : multiChunksEntries) {
        if (dirtyMultiChunkIds.contains(multiChunkEntry.getId())) {
            logger.log(Level.INFO, "- Ignoring multichunk (from dirty database, already uploaded), " + multiChunkEntry.getId() + " ...");
        } else {
            File localMultiChunkFile = config.getCache().getEncryptedMultiChunkFile(multiChunkEntry.getId());
            MultichunkRemoteFile remoteMultiChunkFile = new MultichunkRemoteFile(multiChunkEntry.getId());
            logger.log(Level.INFO, "- Uploading multichunk {0} from {1} to {2} ...", new Object[] { multiChunkEntry.getId(), localMultiChunkFile, remoteMultiChunkFile });
            remoteTransaction.upload(localMultiChunkFile, remoteMultiChunkFile);
        }
    }
}
Also used : MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile) MultiChunkEntry(org.syncany.database.MultiChunkEntry) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) TransactionRemoteFile(org.syncany.plugins.transfer.files.TransactionRemoteFile) File(java.io.File) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile)

Example 19 with MultiChunkId

use of org.syncany.database.MultiChunkEntry.MultiChunkId in project syncany by syncany.

the class ApplyChangesOperation method determineMultiChunksToDownload.

/**
	 * 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;
}
Also used : FileContent(org.syncany.database.FileContent) MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) ChunkChecksum(org.syncany.database.ChunkEntry.ChunkChecksum) HashSet(java.util.HashSet)

Example 20 with MultiChunkId

use of org.syncany.database.MultiChunkEntry.MultiChunkId in project syncany by syncany.

the class GetFileFolderRequestHandler method handleRequest.

@Override
public Response handleRequest(FolderRequest request) {
    GetFileFolderRequest concreteRequest = (GetFileFolderRequest) request;
    try {
        FileHistoryId fileHistoryId = FileHistoryId.parseFileId(concreteRequest.getFileHistoryId());
        long version = concreteRequest.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(), config);
        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));
        GetFileFolderResponse fileResponse = new GetFileFolderResponse(concreteRequest.getId(), concreteRequest.getRoot(), tempFileToken);
        GetFileFolderResponseInternal fileResponseInternal = new GetFileFolderResponseInternal(fileResponse, tempFile);
        eventBus.post(fileResponseInternal);
        return null;
    } catch (Exception e) {
        logger.log(Level.WARNING, "Cannot reassemble file.", e);
        return new BadRequestResponse(concreteRequest.getId(), "Cannot reassemble file.");
    }
}
Also used : TransferManager(org.syncany.plugins.transfer.TransferManager) FileHistoryId(org.syncany.database.PartialFileHistory.FileHistoryId) MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) Downloader(org.syncany.operations.Downloader) ChunkChecksum(org.syncany.database.ChunkEntry.ChunkChecksum) FileContent(org.syncany.database.FileContent) FileVersion(org.syncany.database.FileVersion) Assembler(org.syncany.operations.Assembler) File(java.io.File)

Aggregations

MultiChunkId (org.syncany.database.MultiChunkEntry.MultiChunkId)25 MultiChunkEntry (org.syncany.database.MultiChunkEntry)12 Test (org.junit.Test)10 ChunkChecksum (org.syncany.database.ChunkEntry.ChunkChecksum)10 Connection (java.sql.Connection)8 Config (org.syncany.config.Config)8 MultiChunkSqlDao (org.syncany.database.dao.MultiChunkSqlDao)8 File (java.io.File)6 DatabaseVersion (org.syncany.database.DatabaseVersion)6 FileContent (org.syncany.database.FileContent)6 ChunkEntry (org.syncany.database.ChunkEntry)5 FileOutputStream (java.io.FileOutputStream)4 FileVersion (org.syncany.database.FileVersion)4 FileHistoryId (org.syncany.database.PartialFileHistory.FileHistoryId)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 MultiChunk (org.syncany.chunk.MultiChunk)3 PartialFileHistory (org.syncany.database.PartialFileHistory)3 IOException (java.io.IOException)2