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);
}
}
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();
}
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);
}
}
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"));
}
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));
}
Aggregations