Search in sources :

Example 11 with MemoryDatabase

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

the class MemoryDatabaseCacheTest method testMultiChunkCache.

@Test
public void testMultiChunkCache() throws IOException {
    MemoryDatabase database = new MemoryDatabase();
    // Round 1: Add chunk to multichunk
    DatabaseVersion databaseVersion1 = TestDatabaseUtil.createDatabaseVersion();
    MultiChunkEntry multiChunkP1 = new MultiChunkEntry(new MultiChunkId(new byte[] { 8, 8, 8, 8, 8, 8, 8, 8 }), 10);
    ChunkEntry chunkA1 = new ChunkEntry(new ChunkChecksum(new byte[] { 1, 2, 3, 4, 5, 7, 8, 9, 0 }), 12);
    multiChunkP1.addChunk(chunkA1.getChecksum());
    databaseVersion1.addChunk(chunkA1);
    databaseVersion1.addMultiChunk(multiChunkP1);
    database.addDatabaseVersion(databaseVersion1);
    assertEquals(chunkA1, database.getChunk(new ChunkChecksum(new byte[] { 1, 2, 3, 4, 5, 7, 8, 9, 0 })));
    assertEquals(multiChunkP1, database.getMultiChunk(new MultiChunkId(new byte[] { 8, 8, 8, 8, 8, 8, 8, 8 })));
    // Round 2: Add chunk to multichunk
    DatabaseVersion databaseVersion2 = TestDatabaseUtil.createDatabaseVersion(databaseVersion1);
    MultiChunkEntry multiChunkP2 = new MultiChunkEntry(new MultiChunkId(new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7 }), 11);
    MultiChunkEntry multiChunkP3 = new MultiChunkEntry(new MultiChunkId(new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5 }), 12);
    ChunkEntry chunkA2 = new ChunkEntry(new ChunkChecksum(new byte[] { 9, 2, 3, 4, 5, 7, 8, 9, 0 }), 912);
    ChunkEntry chunkA3 = new ChunkEntry(new ChunkChecksum(new byte[] { 8, 2, 3, 4, 5, 7, 8, 9, 0 }), 812);
    ChunkEntry chunkA4 = new ChunkEntry(new ChunkChecksum(new byte[] { 7, 2, 3, 4, 5, 7, 8, 9, 0 }), 712);
    multiChunkP2.addChunk(chunkA2.getChecksum());
    multiChunkP2.addChunk(chunkA3.getChecksum());
    multiChunkP3.addChunk(chunkA4.getChecksum());
    databaseVersion2.addChunk(chunkA2);
    databaseVersion2.addChunk(chunkA3);
    databaseVersion2.addChunk(chunkA4);
    databaseVersion2.addMultiChunk(multiChunkP2);
    databaseVersion2.addMultiChunk(multiChunkP3);
    database.addDatabaseVersion(databaseVersion2);
    // fail("xx");
    assertEquals(chunkA1, database.getChunk(new ChunkChecksum(new byte[] { 1, 2, 3, 4, 5, 7, 8, 9, 0 })));
    assertEquals(chunkA2, database.getChunk(new ChunkChecksum(new byte[] { 9, 2, 3, 4, 5, 7, 8, 9, 0 })));
    assertEquals(chunkA3, database.getChunk(new ChunkChecksum(new byte[] { 8, 2, 3, 4, 5, 7, 8, 9, 0 })));
    assertEquals(chunkA4, database.getChunk(new ChunkChecksum(new byte[] { 7, 2, 3, 4, 5, 7, 8, 9, 0 })));
    assertEquals(multiChunkP1, database.getMultiChunk(new MultiChunkId(new byte[] { 8, 8, 8, 8, 8, 8, 8, 8 })));
    assertEquals(multiChunkP2, database.getMultiChunk(new MultiChunkId(new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7 })));
    assertEquals(multiChunkP3, database.getMultiChunk(new MultiChunkId(new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5 })));
}
Also used : MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) MultiChunkEntry(org.syncany.database.MultiChunkEntry) ChunkEntry(org.syncany.database.ChunkEntry) MemoryDatabase(org.syncany.database.MemoryDatabase) ChunkChecksum(org.syncany.database.ChunkEntry.ChunkChecksum) MultiChunkEntry(org.syncany.database.MultiChunkEntry) DatabaseVersion(org.syncany.database.DatabaseVersion) Test(org.junit.Test)

Example 12 with MemoryDatabase

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

the class TestDatabaseUtil method readDatabaseFileFromDisk.

public static MemoryDatabase readDatabaseFileFromDisk(File databaseFile, Transformer transformer) throws IOException {
    MemoryDatabase db = new MemoryDatabase();
    DatabaseXmlSerializer dao = new DatabaseXmlSerializer(transformer);
    dao.load(db, databaseFile, null, null, DatabaseReadType.FULL);
    return db;
}
Also used : MemoryDatabase(org.syncany.database.MemoryDatabase) DatabaseXmlSerializer(org.syncany.database.dao.DatabaseXmlSerializer)

Example 13 with MemoryDatabase

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

the class UpOperation method attemptResumeDatabaseVersions.

private Collection<DatabaseVersion> attemptResumeDatabaseVersions(Collection<Long> versions) throws Exception {
    try {
        Collection<DatabaseVersion> databaseVersions = new ArrayList<>();
        for (Long version : versions) {
            File databaseFile = config.getTransactionDatabaseFile(version);
            // If a single database file is missing, we should restart
            if (!databaseFile.exists()) {
                return null;
            }
            DatabaseXmlSerializer databaseSerializer = new DatabaseXmlSerializer();
            MemoryDatabase memoryDatabase = new MemoryDatabase();
            databaseSerializer.load(memoryDatabase, databaseFile, null, null, DatabaseReadType.FULL);
            if (memoryDatabase.getDatabaseVersions().size() == 0) {
                return null;
            }
            databaseVersions.add(memoryDatabase.getLastDatabaseVersion());
        }
        return databaseVersions;
    } catch (Exception e) {
        logger.log(Level.WARNING, "Cannot load database versions from 'state'. Cannot resume.");
        return null;
    }
}
Also used : ArrayList(java.util.ArrayList) MemoryDatabase(org.syncany.database.MemoryDatabase) DatabaseXmlSerializer(org.syncany.database.dao.DatabaseXmlSerializer) 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) StorageException(org.syncany.plugins.transfer.StorageException) SQLException(java.sql.SQLException) IOException(java.io.IOException) DatabaseVersion(org.syncany.database.DatabaseVersion)

Example 14 with MemoryDatabase

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

the class UpOperation method serializeRemoteTransactionsAndMetadata.

/**
	 * Serializes both the remote transaction and the current database version
	 * that would be added if Up was successful.
	 * @param newDatabaseVersion the current metadata
	 */
private void serializeRemoteTransactionsAndMetadata(List<RemoteTransaction> remoteTransactions, List<DatabaseVersion> newDatabaseVersions) {
    try {
        logger.log(Level.INFO, "Persisting status of UpOperation to " + config.getStateDir() + " ...");
        // Collect a list of all database version numbers that will be saved
        List<Long> databaseVersionClocks = new ArrayList<>();
        for (int i = 0; i < remoteTransactions.size(); i++) {
            DatabaseVersion databaseVersion = newDatabaseVersions.get(i);
            long databaseVersionClock = databaseVersion.getVectorClock().getClock(config.getMachineName());
            databaseVersionClocks.add(databaseVersionClock);
        }
        // Write the list of version number to a file, before serializing any transactions!
        // This ensures that no transaction files can exist without a "reference" to them.
        File transactionListFile = config.getTransactionListFile();
        PrintWriter transactionListWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(transactionListFile), "UTF-8"));
        for (Long databaseVersion : databaseVersionClocks) {
            transactionListWriter.println(databaseVersion);
        }
        transactionListWriter.close();
        // For each database version write the transaction and database files
        for (int i = 0; i < remoteTransactions.size(); i++) {
            DatabaseVersion databaseVersion = newDatabaseVersions.get(i);
            long databaseVersionClock = databaseVersionClocks.get(i);
            // Writing transaction file to state dir
            remoteTransactions.get(i).writeToFile(null, config.getTransactionFile(databaseVersionClock));
            // Writing database representation of new database version to state dir
            MemoryDatabase memoryDatabase = new MemoryDatabase();
            memoryDatabase.addDatabaseVersion(databaseVersion);
            DatabaseXmlSerializer dao = new DatabaseXmlSerializer();
            dao.save(memoryDatabase.getDatabaseVersions(), config.getTransactionDatabaseFile(databaseVersionClock));
        }
        // The first transaction may be resumable, so write it to the default transaction file
        remoteTransactions.get(0).writeToFile(null, config.getTransactionFile());
    } catch (Exception e) {
        logger.log(Level.WARNING, "Failure when persisting status of Up: ", e);
    }
}
Also used : ArrayList(java.util.ArrayList) DatabaseXmlSerializer(org.syncany.database.dao.DatabaseXmlSerializer) StorageException(org.syncany.plugins.transfer.StorageException) SQLException(java.sql.SQLException) IOException(java.io.IOException) FileOutputStream(java.io.FileOutputStream) MemoryDatabase(org.syncany.database.MemoryDatabase) OutputStreamWriter(java.io.OutputStreamWriter) 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) DatabaseVersion(org.syncany.database.DatabaseVersion) PrintWriter(java.io.PrintWriter)

Example 15 with MemoryDatabase

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

the class DatabaseFileReader method next.

/**
	 * Loads the winner's database branch into the memory in a {@link MemoryDatabase} object, by using
	 * the already downloaded list of remote database files.
	 *
	 * <p>Because database files can contain multiple {@link DatabaseVersion}s per client, a range for which
	 * to load the database versions must be determined.
	 *
	 * <p><b>Example 1:</b><br />
	 * <pre>
	 *  db-A-0001   (A1)     Already known             Not loaded
	 *  db-A-0005   (A2)     Already known             Not loaded
	 *              (A3)     Already known             Not loaded
	 *              (A4)     Part of winner's branch   Loaded
	 *              (A5)     Purge database version    Ignored (only DEFAULT)
	 *  db-B-0001   (A5,B1)  Part of winner's branch   Loaded
	 *  db-A-0006   (A6,B1)  Part of winner's branch   Loaded
	 * </pre>
	 *
	 * <p>In example 1, only (A4)-(A5) must be loaded from db-A-0005, and not all four database versions.
	 *
	 * <p><b>Other example:</b><br />
	 * <pre>
	 *  db-A-0005   (A1)     Part of winner's branch   Loaded
	 *  db-A-0005   (A2)     Part of winner's branch   Loaded
	 *  db-B-0001   (A2,B1)  Part of winner's branch   Loaded
	 *  db-A-0005   (A3,B1)  Part of winner's branch   Loaded
	 *  db-A-0005   (A4,B1)  Part of winner's branch   Loaded
	 *  db-A-0005   (A5,B1)  Purge database version    Ignored (only DEFAULT)
	 * </pre>
	 *
	 * <p>In example 2, (A1)-(A5,B1) [except (A2,B1)] are contained in db-A-0005 (after merging!), so
	 * db-A-0005 must be processed twice; each time loading separate parts of the file. In this case:
	 * First load (A1)-(A2) from db-A-0005, then load (A2,B1) from db-B-0001, then load (A3,B1)-(A4,B1)
	 * from db-A-0005, and ignore (A5,B1).
	 * @param databaseFileList
	 * @param ignoredMostRecentPurgeVersions
	 *
	 * @return Returns a loaded memory database containing all metadata from the winner's branch
	 */
@Override
public MemoryDatabase next() {
    MemoryDatabase winnerBranchDatabase = new MemoryDatabase();
    String rangeClientName = null;
    VectorClock rangeVersionFrom = null;
    VectorClock rangeVersionTo = null;
    while (branchIndex < winnersApplyBranchList.size() && winnerBranchDatabase.getFileHistories().size() < MAX_FILES) {
        DatabaseVersionHeader currentDatabaseVersionHeader = winnersApplyBranchList.get(branchIndex);
        DatabaseVersionHeader nextDatabaseVersionHeader = (branchIndex + 1 < winnersApplyBranchList.size()) ? winnersApplyBranchList.get(branchIndex + 1) : null;
        // First of range for this client
        if (rangeClientName == null) {
            rangeClientName = currentDatabaseVersionHeader.getClient();
            rangeVersionFrom = currentDatabaseVersionHeader.getVectorClock();
            rangeVersionTo = currentDatabaseVersionHeader.getVectorClock();
        } else // Still in range for this client
        {
            rangeVersionTo = currentDatabaseVersionHeader.getVectorClock();
        }
        // Now load this stuff from the database file (or not)
        //   - If the database file exists, load the range and reset it
        //   - If not, only force a load if this is the range end
        File databaseVersionFile = databaseVersionLocations.get(currentDatabaseVersionHeader);
        if (databaseVersionFile == null) {
            throw new RuntimeException("Could not find file corresponding to " + currentDatabaseVersionHeader + ", while it is in the winners branch.");
        }
        boolean lastDatabaseVersionHeader = nextDatabaseVersionHeader == null;
        boolean nextDatabaseVersionInSameFile = lastDatabaseVersionHeader || databaseVersionFile.equals(databaseVersionLocations.get(nextDatabaseVersionHeader));
        boolean rangeEnds = lastDatabaseVersionHeader || !nextDatabaseVersionInSameFile;
        if (rangeEnds) {
            try {
                databaseSerializer.load(winnerBranchDatabase, databaseVersionFile, rangeVersionFrom, rangeVersionTo, DatabaseReadType.FULL);
            } catch (IOException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
            rangeClientName = null;
        }
        branchIndex++;
    }
    return winnerBranchDatabase;
}
Also used : VectorClock(org.syncany.database.VectorClock) MemoryDatabase(org.syncany.database.MemoryDatabase) IOException(java.io.IOException) DatabaseVersionHeader(org.syncany.database.DatabaseVersionHeader) File(java.io.File)

Aggregations

MemoryDatabase (org.syncany.database.MemoryDatabase)26 DatabaseVersion (org.syncany.database.DatabaseVersion)20 Test (org.junit.Test)16 File (java.io.File)9 FileVersion (org.syncany.database.FileVersion)8 PartialFileHistory (org.syncany.database.PartialFileHistory)8 ChunkEntry (org.syncany.database.ChunkEntry)7 ChunkChecksum (org.syncany.database.ChunkEntry.ChunkChecksum)7 MultiChunkEntry (org.syncany.database.MultiChunkEntry)7 ArrayList (java.util.ArrayList)6 FileHistoryId (org.syncany.database.PartialFileHistory.FileHistoryId)6 DatabaseXmlSerializer (org.syncany.database.dao.DatabaseXmlSerializer)5 DatabaseRemoteFile (org.syncany.plugins.transfer.files.DatabaseRemoteFile)5 IOException (java.io.IOException)3 FileChecksum (org.syncany.database.FileContent.FileChecksum)3 VectorClock (org.syncany.database.VectorClock)3 MultichunkRemoteFile (org.syncany.plugins.transfer.files.MultichunkRemoteFile)3 TransactionRemoteFile (org.syncany.plugins.transfer.files.TransactionRemoteFile)3 SQLException (java.sql.SQLException)2 HashMap (java.util.HashMap)2