Search in sources :

Example 16 with DatabaseRemoteFile

use of org.syncany.plugins.transfer.files.DatabaseRemoteFile in project syncany by syncany.

the class CleanupOperation method mergeRemoteFiles.

/**
	 * This method deletes all remote database files and writes new ones for each client using the local database.
	 * To make the state clear and prevent issues with replacing files, new database files are given a higher number
	 * than all existing database files.
	 * Both the deletions and the new files added to the current @{link RemoteTransaction}.
	 */
private void mergeRemoteFiles() throws Exception {
    // Retrieve all database versions
    Map<String, List<DatabaseRemoteFile>> allDatabaseFilesMap = retrieveAllRemoteDatabaseFiles();
    boolean needMerge = needMerge(allDatabaseFilesMap);
    if (!needMerge) {
        logger.log(Level.INFO, "- No purging happened. Number of database files does not exceed threshold. Not merging remote files.");
        return;
    }
    // Now do the merge!
    logger.log(Level.INFO, "- Merge remote files ...");
    List<DatabaseRemoteFile> allToDeleteDatabaseFiles = new ArrayList<DatabaseRemoteFile>();
    Map<File, DatabaseRemoteFile> allMergedDatabaseFiles = new TreeMap<File, DatabaseRemoteFile>();
    for (String client : allDatabaseFilesMap.keySet()) {
        List<DatabaseRemoteFile> clientDatabaseFiles = allDatabaseFilesMap.get(client);
        Collections.sort(clientDatabaseFiles);
        logger.log(Level.INFO, "Databases: " + clientDatabaseFiles);
        // 1. Determine files to delete remotely
        List<DatabaseRemoteFile> toDeleteDatabaseFiles = new ArrayList<DatabaseRemoteFile>(clientDatabaseFiles);
        allToDeleteDatabaseFiles.addAll(toDeleteDatabaseFiles);
        // 2. Write new database file and save it in allMergedDatabaseFiles
        writeMergeFile(client, allMergedDatabaseFiles);
    }
    rememberDatabases(allMergedDatabaseFiles);
    // Queue old databases for deletion
    for (RemoteFile toDeleteRemoteFile : allToDeleteDatabaseFiles) {
        logger.log(Level.INFO, "   + Deleting remote file " + toDeleteRemoteFile + " ...");
        remoteTransaction.delete(toDeleteRemoteFile);
    }
    // Queue new databases for uploading
    for (File lastLocalMergeDatabaseFile : allMergedDatabaseFiles.keySet()) {
        RemoteFile lastRemoteMergeDatabaseFile = allMergedDatabaseFiles.get(lastLocalMergeDatabaseFile);
        logger.log(Level.INFO, "   + Uploading new file {0} from local file {1} ...", new Object[] { lastRemoteMergeDatabaseFile, lastLocalMergeDatabaseFile });
        remoteTransaction.upload(lastLocalMergeDatabaseFile, lastRemoteMergeDatabaseFile);
    }
    finishMerging();
    // Update stats
    result.setMergedDatabaseFilesCount(allToDeleteDatabaseFiles.size());
}
Also used : DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) TreeMap(java.util.TreeMap) RemoteFile(org.syncany.plugins.transfer.files.RemoteFile) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) CleanupRemoteFile(org.syncany.plugins.transfer.files.CleanupRemoteFile) File(java.io.File) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile) RemoteFile(org.syncany.plugins.transfer.files.RemoteFile) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) CleanupRemoteFile(org.syncany.plugins.transfer.files.CleanupRemoteFile) MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile)

Example 17 with DatabaseRemoteFile

use of org.syncany.plugins.transfer.files.DatabaseRemoteFile in project syncany by syncany.

the class ApplicationSqlDao method writeKnownRemoteDatabases.

/**
	 * Writes a list of {@link DatabaseRemoteFile}s to the database using the given connection.
	 * <p><b>Note:</b> This method executes, but does not commit the query.
	 *
	 * @param remoteDatabases List of remote databases to write to the database
	 * @throws SQLException If the SQL statement fails
	 */
public void writeKnownRemoteDatabases(List<DatabaseRemoteFile> remoteDatabases) throws SQLException {
    if (remoteDatabases.size() == 0) {
        // Nothing to write
        return;
    }
    PreparedStatement preparedStatement = getStatement("application.insert.all.persistNewKnownRemoteDatabases.sql");
    for (DatabaseRemoteFile databaseRemoteFile : remoteDatabases) {
        preparedStatement.setString(1, databaseRemoteFile.getClientName());
        preparedStatement.setInt(2, (int) databaseRemoteFile.getClientVersion());
        preparedStatement.addBatch();
    }
    preparedStatement.executeBatch();
}
Also used : DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) PreparedStatement(java.sql.PreparedStatement)

Example 18 with DatabaseRemoteFile

use of org.syncany.plugins.transfer.files.DatabaseRemoteFile in project syncany by syncany.

the class DownOperation method purgeConflictingLocalBranch.

/**
	 * Marks locally conflicting database versions as <tt>DIRTY</tt> and removes remote databases that
	 * correspond to those database versions. This method uses the {@link DatabaseReconciliator}
	 * to determine whether there is a local purge branch.
	 */
private void purgeConflictingLocalBranch(DatabaseBranch localBranch, Entry<String, DatabaseBranch> winnersBranch) throws Exception {
    DatabaseBranch localPurgeBranch = databaseReconciliator.findLosersPruneBranch(localBranch, winnersBranch.getValue());
    logger.log(Level.INFO, "- Database versions to REMOVE locally: " + localPurgeBranch);
    if (localPurgeBranch.size() == 0) {
        logger.log(Level.INFO, "  + Nothing to purge locally. No conflicts. Only updates. Nice!");
    } else {
        // Load dirty database (if existent)
        logger.log(Level.INFO, "  + Marking databases as DIRTY locally ...");
        for (DatabaseVersionHeader databaseVersionHeader : localPurgeBranch.getAll()) {
            logger.log(Level.INFO, "    * MASTER->DIRTY: " + databaseVersionHeader);
            localDatabase.markDatabaseVersionDirty(databaseVersionHeader.getVectorClock());
            boolean isOwnDatabaseVersionHeader = config.getMachineName().equals(databaseVersionHeader.getClient());
            if (isOwnDatabaseVersionHeader) {
                String remoteFileToPruneClientName = config.getMachineName();
                long remoteFileToPruneVersion = databaseVersionHeader.getVectorClock().getClock(config.getMachineName());
                DatabaseRemoteFile remoteFileToPrune = new DatabaseRemoteFile(remoteFileToPruneClientName, remoteFileToPruneVersion);
                logger.log(Level.INFO, "    * Deleting own remote database file " + remoteFileToPrune + " ...");
                transferManager.delete(remoteFileToPrune);
            } else {
                logger.log(Level.INFO, "    * NOT deleting any database file remotely (not our database!)");
            }
            result.getDirtyDatabasesCreated().add(databaseVersionHeader);
        }
    }
}
Also used : DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) DatabaseVersionHeader(org.syncany.database.DatabaseVersionHeader)

Example 19 with DatabaseRemoteFile

use of org.syncany.plugins.transfer.files.DatabaseRemoteFile in project syncany by syncany.

the class DownOperation method readUnknownDatabaseVersionHeaders.

/**
	 * Read the given database files into individual per-user {@link DatabaseBranch}es. This method only
	 * reads the headers from the local database files, and not the entire databases into memory.
	 *
	 * <p>The returned database branches contain only the per-client {@link DatabaseVersionHeader}s, and not
	 * the entire stitched branches, i.e. A's database branch will only contain database version headers from A.
	 */
private SortedMap<DatabaseRemoteFile, List<DatabaseVersion>> readUnknownDatabaseVersionHeaders(SortedMap<File, DatabaseRemoteFile> remoteDatabases) throws IOException, StorageException {
    logger.log(Level.INFO, "Loading database headers, creating branches ...");
    // Read database files
    SortedMap<DatabaseRemoteFile, List<DatabaseVersion>> remoteDatabaseHeaders = new TreeMap<DatabaseRemoteFile, List<DatabaseVersion>>();
    for (Map.Entry<File, DatabaseRemoteFile> remoteDatabaseFileEntry : remoteDatabases.entrySet()) {
        // Database cannot be reused, since these might be different clients
        MemoryDatabase remoteDatabase = new MemoryDatabase();
        File remoteDatabaseFileInCache = remoteDatabaseFileEntry.getKey();
        DatabaseRemoteFile remoteDatabaseFile = remoteDatabaseFileEntry.getValue();
        // only load headers!
        databaseSerializer.load(remoteDatabase, remoteDatabaseFileInCache, null, null, DatabaseReadType.HEADER_ONLY);
        remoteDatabaseHeaders.put(remoteDatabaseFile, remoteDatabase.getDatabaseVersions());
    }
    return remoteDatabaseHeaders;
}
Also used : DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) MemoryDatabase(org.syncany.database.MemoryDatabase) List(java.util.List) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) Map(java.util.Map) AbstractMap(java.util.AbstractMap) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) CleanupRemoteFile(org.syncany.plugins.transfer.files.CleanupRemoteFile) File(java.io.File) DatabaseVersion(org.syncany.database.DatabaseVersion)

Example 20 with DatabaseRemoteFile

use of org.syncany.plugins.transfer.files.DatabaseRemoteFile in project syncany by syncany.

the class LsRemoteOperation method execute.

@Override
public LsRemoteOperationResult execute() throws Exception {
    logger.log(Level.INFO, "");
    logger.log(Level.INFO, "Running 'Remote Status' at client " + config.getMachineName() + " ...");
    logger.log(Level.INFO, "--------------------------------------------");
    eventBus.post(new LsRemoteStartSyncExternalEvent(config.getLocalDir().getAbsolutePath()));
    TransferManager transferManager = createTransferManager(loadedTransferManager);
    List<DatabaseRemoteFile> knownDatabases = localDatabase.getKnownDatabases();
    List<DatabaseRemoteFile> unknownRemoteDatabases = listUnknownRemoteDatabases(transferManager, knownDatabases);
    transferManager.disconnect();
    boolean hasChanges = unknownRemoteDatabases.size() > 0;
    eventBus.post(new LsRemoteEndSyncExternalEvent(config.getLocalDir().getAbsolutePath(), hasChanges));
    return new LsRemoteOperationResult(new ArrayList<>(unknownRemoteDatabases));
}
Also used : TransferManager(org.syncany.plugins.transfer.TransferManager) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) LsRemoteStartSyncExternalEvent(org.syncany.operations.daemon.messages.LsRemoteStartSyncExternalEvent) LsRemoteEndSyncExternalEvent(org.syncany.operations.daemon.messages.LsRemoteEndSyncExternalEvent)

Aggregations

DatabaseRemoteFile (org.syncany.plugins.transfer.files.DatabaseRemoteFile)22 File (java.io.File)11 Test (org.junit.Test)8 MultichunkRemoteFile (org.syncany.plugins.transfer.files.MultichunkRemoteFile)5 RemoteFile (org.syncany.plugins.transfer.files.RemoteFile)5 ArrayList (java.util.ArrayList)4 DatabaseVersion (org.syncany.database.DatabaseVersion)4 CleanupRemoteFile (org.syncany.plugins.transfer.files.CleanupRemoteFile)4 Connection (java.sql.Connection)3 TreeMap (java.util.TreeMap)3 Config (org.syncany.config.Config)3 ApplicationSqlDao (org.syncany.database.dao.ApplicationSqlDao)3 PreparedStatement (java.sql.PreparedStatement)2 List (java.util.List)2 CommandLineClient (org.syncany.cli.CommandLineClient)2 DatabaseVersionHeader (org.syncany.database.DatabaseVersionHeader)2 MemoryDatabase (org.syncany.database.MemoryDatabase)2 LsRemoteOperationResult (org.syncany.operations.ls_remote.LsRemoteOperationResult)2 TransferManager (org.syncany.plugins.transfer.TransferManager)2 MasterRemoteFile (org.syncany.plugins.transfer.files.MasterRemoteFile)2