Search in sources :

Example 1 with VectorClock

use of org.syncany.database.VectorClock in project syncany by syncany.

the class DownOperation method persistMuddyMultiChunks.

/**
 * Identifies and persists 'muddy' multichunks to the local database. Muddy multichunks are multichunks
 * that have been referenced by DIRTY database versions and might be reused in future database versions when
 * the other client cleans up its mess (performs another 'up').
 */
private void persistMuddyMultiChunks(Entry<String, DatabaseBranch> winnersBranch, DatabaseBranches allStitchedBranches, Map<DatabaseVersionHeader, File> databaseVersionLocations) throws StorageException, IOException, SQLException {
    // Find dirty database versions (from other clients!) and load them from files
    Map<DatabaseVersionHeader, Collection<MultiChunkEntry>> muddyMultiChunksPerDatabaseVersion = new HashMap<>();
    Set<DatabaseVersionHeader> winnersDatabaseVersionHeaders = Sets.newHashSet(winnersBranch.getValue().getAll());
    for (String otherClientName : allStitchedBranches.getClients()) {
        boolean isLocalMachine = config.getMachineName().equals(otherClientName);
        if (!isLocalMachine) {
            DatabaseBranch otherClientBranch = allStitchedBranches.getBranch(otherClientName);
            Set<DatabaseVersionHeader> otherClientDatabaseVersionHeaders = Sets.newHashSet(otherClientBranch.getAll());
            SetView<DatabaseVersionHeader> otherMuddyDatabaseVersionHeaders = Sets.difference(otherClientDatabaseVersionHeaders, winnersDatabaseVersionHeaders);
            boolean hasMuddyDatabaseVersionHeaders = otherMuddyDatabaseVersionHeaders.size() > 0;
            if (hasMuddyDatabaseVersionHeaders) {
                logger.log(Level.INFO, "DIRTY database version headers of " + otherClientName + ":  " + otherMuddyDatabaseVersionHeaders);
                for (DatabaseVersionHeader muddyDatabaseVersionHeader : otherMuddyDatabaseVersionHeaders) {
                    MemoryDatabase muddyMultiChunksDatabase = new MemoryDatabase();
                    File localFileForMuddyDatabaseVersion = databaseVersionLocations.get(muddyDatabaseVersionHeader);
                    VectorClock fromVersion = muddyDatabaseVersionHeader.getVectorClock();
                    VectorClock toVersion = muddyDatabaseVersionHeader.getVectorClock();
                    logger.log(Level.INFO, "  - Loading " + muddyDatabaseVersionHeader + " from file " + localFileForMuddyDatabaseVersion);
                    databaseSerializer.load(muddyMultiChunksDatabase, localFileForMuddyDatabaseVersion, fromVersion, toVersion, DatabaseReadType.FULL);
                    boolean hasMuddyMultiChunks = muddyMultiChunksDatabase.getMultiChunks().size() > 0;
                    if (hasMuddyMultiChunks) {
                        muddyMultiChunksPerDatabaseVersion.put(muddyDatabaseVersionHeader, muddyMultiChunksDatabase.getMultiChunks());
                    }
                }
            }
        }
    }
    // Add muddy multichunks to 'multichunks_muddy' database table
    boolean hasMuddyMultiChunks = muddyMultiChunksPerDatabaseVersion.size() > 0;
    if (hasMuddyMultiChunks) {
        localDatabase.writeMuddyMultiChunks(muddyMultiChunksPerDatabaseVersion);
    }
}
Also used : HashMap(java.util.HashMap) VectorClock(org.syncany.database.VectorClock) MemoryDatabase(org.syncany.database.MemoryDatabase) Collection(java.util.Collection) DatabaseVersionHeader(org.syncany.database.DatabaseVersionHeader) DatabaseRemoteFile(org.syncany.plugins.transfer.files.DatabaseRemoteFile) CleanupRemoteFile(org.syncany.plugins.transfer.files.CleanupRemoteFile) File(java.io.File)

Example 2 with VectorClock

use of org.syncany.database.VectorClock in project syncany by syncany.

the class DatabaseXmlWriter method writeDatabaseVersionHeader.

private void writeDatabaseVersionHeader(IndentXmlStreamWriter xmlOut, DatabaseVersion databaseVersion) throws IOException, XMLStreamException {
    if (databaseVersion.getTimestamp() == null || databaseVersion.getClient() == null || databaseVersion.getVectorClock() == null || databaseVersion.getVectorClock().isEmpty()) {
        logger.log(Level.SEVERE, "Cannot write database version. Header fields must be filled: " + databaseVersion.getHeader());
        throw new IOException("Cannot write database version. Header fields must be filled: " + databaseVersion.getHeader());
    }
    xmlOut.writeStartElement("header");
    xmlOut.writeEmptyElement("time");
    xmlOut.writeAttribute("value", databaseVersion.getTimestamp().getTime());
    xmlOut.writeEmptyElement("client");
    xmlOut.writeAttribute("name", databaseVersion.getClient());
    xmlOut.writeStartElement("vectorClock");
    VectorClock vectorClock = databaseVersion.getVectorClock();
    for (Map.Entry<String, Long> vectorClockEntry : vectorClock.entrySet()) {
        xmlOut.writeEmptyElement("client");
        xmlOut.writeAttribute("name", vectorClockEntry.getKey());
        xmlOut.writeAttribute("value", vectorClockEntry.getValue());
    }
    // </vectorClock>
    xmlOut.writeEndElement();
    // </header>
    xmlOut.writeEndElement();
}
Also used : VectorClock(org.syncany.database.VectorClock) IOException(java.io.IOException) Map(java.util.Map)

Example 3 with VectorClock

use of org.syncany.database.VectorClock in project syncany by syncany.

the class FileHistorySqlDao method getFileHistoryWithLastVersionByPath.

/**
 * This function returns a FileHistory, with as last version a FileVersion with
 * the given path.
 *
 * If the last FileVersion referring to this path is not the last in the
 * FileHistory, or no such FileVersion exists, null is returned.
 */
public PartialFileHistory getFileHistoryWithLastVersionByPath(String path) {
    try (PreparedStatement preparedStatement = getStatement("filehistory.select.master.findLatestFileVersionsForPath.sql")) {
        preparedStatement.setString(1, path);
        try (ResultSet resultSet = preparedStatement.executeQuery()) {
            // Fetch the latest versions of all files that once existed with the given
            // path and find the most recent by comparing vector clocks
            String latestFileHistoryId = null;
            Long latestFileVersion = null;
            VectorClock latestVectorClock = null;
            while (resultSet.next()) {
                VectorClock resultSetVectorClock = VectorClock.parseVectorClock(resultSet.getString("vectorclock_serialized"));
                boolean vectorClockIsGreater = latestVectorClock == null || VectorClock.compare(resultSetVectorClock, latestVectorClock) == VectorClock.VectorClockComparison.GREATER;
                if (vectorClockIsGreater) {
                    latestVectorClock = resultSetVectorClock;
                    latestFileHistoryId = resultSet.getString("filehistory_id");
                    latestFileVersion = resultSet.getLong("version");
                }
            }
            // If no active file history exists for this path, return
            if (latestFileHistoryId == null) {
                return null;
            }
            // Get the last FileVersion of the FileHistory in the database with the largest vectorclock.
            PartialFileHistory fileHistory = getLastVersionByFileHistoryId(latestFileHistoryId);
            // history. We need to check this before returning the file.
            if (fileHistory.getLastVersion().getVersion() == latestFileVersion) {
                return fileHistory;
            } else {
                // which should be continued.
                return null;
            }
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}
Also used : SQLException(java.sql.SQLException) VectorClock(org.syncany.database.VectorClock) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) PartialFileHistory(org.syncany.database.PartialFileHistory)

Example 4 with VectorClock

use of org.syncany.database.VectorClock in project syncany by syncany.

the class VectorClockTest method testIncrementUnit.

@Test
public void testIncrementUnit() {
    VectorClock vc = new VectorClock();
    vc.setClock("UnitA", 1);
    // 2
    vc.incrementClock("UnitA");
    // 3
    vc.incrementClock("UnitA");
    vc.setClock("UnitB", 2);
    // 3
    vc.incrementClock("UnitB");
    assertEquals("Expected clock value to be different.", 3L, (long) vc.getClock("UnitA"));
    assertEquals("Expected clock value to be different.", 3L, (long) vc.getClock("UnitB"));
}
Also used : VectorClock(org.syncany.database.VectorClock) Test(org.junit.Test)

Example 5 with VectorClock

use of org.syncany.database.VectorClock in project syncany by syncany.

the class VectorClockTest method testCompareSmallerClocksWithSameUnitCount.

@Test
public void testCompareSmallerClocksWithSameUnitCount() {
    VectorClock vc1 = new VectorClock();
    vc1.setClock("UnitA", 4L);
    vc1.setClock("UnitB", 5L);
    VectorClock vc2 = new VectorClock();
    vc2.setClock("UnitA", 4L);
    // greater!
    vc2.setClock("UnitB", 100000L);
    assertEquals("Expected clock 1 to be smaller than clock 2.", VectorClockComparison.SMALLER, VectorClock.compare(vc1, vc2));
    assertEquals("Expected clock 2 to be greater than clock 1.", VectorClockComparison.GREATER, VectorClock.compare(vc2, vc1));
}
Also used : VectorClock(org.syncany.database.VectorClock) Test(org.junit.Test)

Aggregations

VectorClock (org.syncany.database.VectorClock)28 Test (org.junit.Test)14 IOException (java.io.IOException)5 Date (java.util.Date)5 DatabaseVersion (org.syncany.database.DatabaseVersion)5 DatabaseVersionHeader (org.syncany.database.DatabaseVersionHeader)5 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 MemoryDatabase (org.syncany.database.MemoryDatabase)3 File (java.io.File)2 Matcher (java.util.regex.Matcher)2 PartialFileHistory (org.syncany.database.PartialFileHistory)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Before (org.junit.Before)1 ChunkEntry (org.syncany.database.ChunkEntry)1