Search in sources :

Example 6 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 7 with VectorClock

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

the class UpOperation method findNewVectorClock.

/**
 * Finds the next vector clock
 *
 * <p>There are two causes for not having a previous vector clock:
 * <ul>
 *   <li>This is the initial version
 *   <li>A cleanup has wiped *all* database versions
 * </ul>
 *
 * In the latter case, the method looks at the previous database version numbers
 * to determine a new vector clock
 */
private VectorClock findNewVectorClock() {
    // Get last vector clock
    DatabaseVersionHeader lastDatabaseVersionHeader = localDatabase.getLastDatabaseVersionHeader();
    VectorClock lastVectorClock = (lastDatabaseVersionHeader != null) ? lastDatabaseVersionHeader.getVectorClock() : new VectorClock();
    logger.log(Level.INFO, "Last vector clock was: " + lastVectorClock);
    boolean noPreviousVectorClock = lastVectorClock.isEmpty();
    if (noPreviousVectorClock) {
        lastVectorClock = localDatabase.getHighestKnownDatabaseFilenameNumbers();
    }
    VectorClock newVectorClock = lastVectorClock.clone();
    Long lastLocalValue = lastVectorClock.getClock(config.getMachineName());
    Long lastDirtyLocalValue = localDatabase.getMaxDirtyVectorClock(config.getMachineName());
    Long newLocalValue = null;
    if (lastDirtyLocalValue != null) {
        newLocalValue = lastDirtyLocalValue + 1;
    } else {
        if (lastLocalValue != null) {
            newLocalValue = lastLocalValue + 1;
        } else {
            newLocalValue = 1L;
        }
    }
    newVectorClock.setClock(config.getMachineName(), newLocalValue);
    return newVectorClock;
}
Also used : VectorClock(org.syncany.database.VectorClock) DatabaseVersionHeader(org.syncany.database.DatabaseVersionHeader)

Example 8 with VectorClock

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

the class TestDatabaseUtil method createFromString.

public static DatabaseVersionHeader createFromString(String databaseVersionHeaderString) throws Exception {
    Matcher databaseVersionHeaderMatcher = databaseVersionHeaderPattern.matcher(databaseVersionHeaderString);
    if (!databaseVersionHeaderMatcher.matches()) {
        throw new Exception("Invalid database version header string: " + databaseVersionHeaderString);
    }
    String client = databaseVersionHeaderMatcher.group(1);
    String vectorClockString = databaseVersionHeaderMatcher.group(2);
    long databaseVersionHeaderTime = Long.parseLong(databaseVersionHeaderMatcher.group(3));
    VectorClock vectorClock = createVectorClock(vectorClockString);
    DatabaseVersionHeader newDatabaseVersionHeader = new DatabaseVersionHeader();
    newDatabaseVersionHeader.setDate(new Date(databaseVersionHeaderTime));
    newDatabaseVersionHeader.setVectorClock(vectorClock);
    newDatabaseVersionHeader.setClient(client);
    return newDatabaseVersionHeader;
}
Also used : Matcher(java.util.regex.Matcher) VectorClock(org.syncany.database.VectorClock) DatabaseVersionHeader(org.syncany.database.DatabaseVersionHeader) IOException(java.io.IOException) Date(java.util.Date)

Example 9 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 10 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)

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