Search in sources :

Example 6 with MultiChunkEntry

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

the class DatabaseVersionDaoTest method testRemoveDirtyDatabaseVersions.

@Test
public void testRemoveDirtyDatabaseVersions() throws Exception {
    // Setup
    Config testConfig = TestConfigUtil.createTestLocalConfig();
    Connection databaseConnection = testConfig.createDatabaseConnection();
    // Run
    TestSqlUtil.runSqlFromResource(databaseConnection, "test.insert.set1.sql");
    ChunkSqlDao chunkDao = new ChunkSqlDao(databaseConnection);
    MultiChunkSqlDao multiChunkDao = new MultiChunkSqlDao(databaseConnection);
    FileVersionSqlDao fileVersionDao = new FileVersionSqlDao(databaseConnection);
    FileHistorySqlDao fileHistoryDao = new FileHistorySqlDao(databaseConnection, fileVersionDao);
    FileContentSqlDao fileContentDao = new FileContentSqlDao(databaseConnection);
    DatabaseVersionSqlDao databaseVersionDao = new DatabaseVersionSqlDao(databaseConnection, chunkDao, fileContentDao, fileVersionDao, fileHistoryDao, multiChunkDao);
    // a. Test before
    List<DatabaseVersion> dirtyDatabaseVersionsBefore = TestCollectionUtil.toList(databaseVersionDao.getDirtyDatabaseVersions());
    assertNotNull(dirtyDatabaseVersionsBefore);
    assertNotNull(chunkDao.getChunk(ChunkChecksum.parseChunkChecksum("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef")));
    assertNotNull(multiChunkDao.getDirtyMultiChunkIds());
    assertEquals(1, multiChunkDao.getDirtyMultiChunkIds().size());
    // b. Add new database version with DIRTY multichunk; remove DIRTY version
    DatabaseVersion newDatabaseVersion = new DatabaseVersion();
    newDatabaseVersion.setVectorClock(TestDatabaseUtil.createVectorClock("A5,B2"));
    long newDatabaseVersionId = databaseVersionDao.writeDatabaseVersion(newDatabaseVersion);
    databaseVersionDao.removeDirtyDatabaseVersions(newDatabaseVersionId);
    // c. Test after
    // Database version
    List<DatabaseVersion> dirtyDatabaseVersionsAfter = TestCollectionUtil.toList(databaseVersionDao.getDirtyDatabaseVersions());
    assertNotNull(dirtyDatabaseVersionsAfter);
    assertEquals(0, dirtyDatabaseVersionsAfter.size());
    // Multichunk from dirty version "moved" to new version
    Map<MultiChunkId, MultiChunkEntry> multiChunksA5B2 = multiChunkDao.getMultiChunks(TestDatabaseUtil.createVectorClock("A5,B2"));
    assertNotNull(multiChunksA5B2);
    assertEquals(1, multiChunksA5B2.size());
    assertNotNull(multiChunksA5B2.get(MultiChunkId.parseMultiChunkId("1234567890987654321123456789098765433222")));
    // File version/history/content ARE removed
    assertNull(fileContentDao.getFileContent(FileChecksum.parseFileChecksum("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef"), true));
    // TODO [low] Test file version and file history removal
    // Chunks and multichunks are NOT removed!
    assertNotNull(chunkDao.getChunk(ChunkChecksum.parseChunkChecksum("beefbeefbeefbeefbeefbeefbeefbeefbeefbeef")));
    assertNotNull(multiChunkDao.getMultiChunks(TestDatabaseUtil.createVectorClock("B1")));
    assertEquals(0, multiChunkDao.getMultiChunks(TestDatabaseUtil.createVectorClock("B1")).size());
    assertNotNull(multiChunkDao.getDirtyMultiChunkIds());
    assertEquals(0, multiChunkDao.getDirtyMultiChunkIds().size());
    // Tear down
    databaseConnection.close();
    TestConfigUtil.deleteTestLocalConfigAndData(testConfig);
}
Also used : MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) Config(org.syncany.config.Config) Connection(java.sql.Connection) DatabaseVersionSqlDao(org.syncany.database.dao.DatabaseVersionSqlDao) MultiChunkSqlDao(org.syncany.database.dao.MultiChunkSqlDao) ChunkSqlDao(org.syncany.database.dao.ChunkSqlDao) MultiChunkSqlDao(org.syncany.database.dao.MultiChunkSqlDao) FileVersionSqlDao(org.syncany.database.dao.FileVersionSqlDao) FileContentSqlDao(org.syncany.database.dao.FileContentSqlDao) MultiChunkEntry(org.syncany.database.MultiChunkEntry) FileHistorySqlDao(org.syncany.database.dao.FileHistorySqlDao) DatabaseVersion(org.syncany.database.DatabaseVersion) Test(org.junit.Test)

Example 7 with MultiChunkEntry

use of org.syncany.database.MultiChunkEntry 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 8 with MultiChunkEntry

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

the class DatabaseXmlParseHandler method startElement.

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    elementPath += "/" + qName;
    if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion")) {
        databaseVersion = new DatabaseVersion();
    } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/header/time")) {
        Date timeValue = new Date(Long.parseLong(attributes.getValue("value")));
        databaseVersion.setTimestamp(timeValue);
    } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/header/client")) {
        String clientName = attributes.getValue("name");
        databaseVersion.setClient(clientName);
    } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/header/vectorClock")) {
        vectorClock = new VectorClock();
    } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/header/vectorClock/client")) {
        String clientName = attributes.getValue("name");
        Long clientValue = Long.parseLong(attributes.getValue("value"));
        vectorClock.setClock(clientName, clientValue);
    } else if (readType == DatabaseReadType.FULL) {
        if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/chunks/chunk")) {
            String chunkChecksumStr = attributes.getValue("checksum");
            ChunkChecksum chunkChecksum = ChunkChecksum.parseChunkChecksum(chunkChecksumStr);
            int chunkSize = Integer.parseInt(attributes.getValue("size"));
            ChunkEntry chunkEntry = new ChunkEntry(chunkChecksum, chunkSize);
            databaseVersion.addChunk(chunkEntry);
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/fileContents/fileContent")) {
            String checksumStr = attributes.getValue("checksum");
            long size = Long.parseLong(attributes.getValue("size"));
            fileContent = new FileContent();
            fileContent.setChecksum(FileChecksum.parseFileChecksum(checksumStr));
            fileContent.setSize(size);
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/fileContents/fileContent/chunkRefs/chunkRef")) {
            String chunkChecksumStr = attributes.getValue("ref");
            fileContent.addChunk(ChunkChecksum.parseChunkChecksum(chunkChecksumStr));
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/multiChunks/multiChunk")) {
            String multChunkIdStr = attributes.getValue("id");
            MultiChunkId multiChunkId = MultiChunkId.parseMultiChunkId(multChunkIdStr);
            long size = Long.parseLong(attributes.getValue("size"));
            if (multiChunkId == null) {
                throw new SAXException("Cannot read ID from multichunk " + multChunkIdStr);
            }
            multiChunk = new MultiChunkEntry(multiChunkId, size);
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/multiChunks/multiChunk/chunkRefs/chunkRef")) {
            String chunkChecksumStr = attributes.getValue("ref");
            multiChunk.addChunk(ChunkChecksum.parseChunkChecksum(chunkChecksumStr));
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/fileHistories/fileHistory")) {
            String fileHistoryIdStr = attributes.getValue("id");
            FileHistoryId fileId = FileHistoryId.parseFileId(fileHistoryIdStr);
            fileHistory = new PartialFileHistory(fileId);
        } else if (elementPath.equalsIgnoreCase("/database/databaseVersions/databaseVersion/fileHistories/fileHistory/fileVersions/fileVersion")) {
            String fileVersionStr = attributes.getValue("version");
            String path = attributes.getValue("path");
            String pathEncoded = attributes.getValue("pathEncoded");
            String sizeStr = attributes.getValue("size");
            String typeStr = attributes.getValue("type");
            String statusStr = attributes.getValue("status");
            String lastModifiedStr = attributes.getValue("lastModified");
            String updatedStr = attributes.getValue("updated");
            String checksumStr = attributes.getValue("checksum");
            String linkTarget = attributes.getValue("linkTarget");
            String dosAttributes = attributes.getValue("dosattrs");
            String posixPermissions = attributes.getValue("posixperms");
            if (fileVersionStr == null || (path == null && pathEncoded == null) || typeStr == null || statusStr == null || sizeStr == null || lastModifiedStr == null) {
                throw new SAXException("FileVersion: Attributes missing: version, path/pathEncoded, type, status, size and last modified are mandatory");
            }
            // Filter it if it was purged somewhere in the future, see #58
            Long fileVersionNum = Long.parseLong(fileVersionStr);
            // Go add it!
            FileVersion fileVersion = new FileVersion();
            fileVersion.setVersion(fileVersionNum);
            if (path != null) {
                fileVersion.setPath(path);
            } else {
                try {
                    fileVersion.setPath(new String(Base64.decodeBase64(pathEncoded), "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException("Invalid Base64 encoding for filename: " + pathEncoded);
                }
            }
            fileVersion.setType(FileType.valueOf(typeStr));
            fileVersion.setStatus(FileStatus.valueOf(statusStr));
            fileVersion.setSize(Long.parseLong(sizeStr));
            fileVersion.setLastModified(new Date(Long.parseLong(lastModifiedStr)));
            if (updatedStr != null) {
                fileVersion.setUpdated(new Date(Long.parseLong(updatedStr)));
            }
            if (checksumStr != null) {
                fileVersion.setChecksum(FileChecksum.parseFileChecksum(checksumStr));
            }
            if (linkTarget != null) {
                fileVersion.setLinkTarget(linkTarget);
            }
            if (dosAttributes != null) {
                fileVersion.setDosAttributes(dosAttributes);
            }
            if (posixPermissions != null) {
                fileVersion.setPosixPermissions(posixPermissions);
            }
            fileHistory.addFileVersion(fileVersion);
        }
    }
}
Also used : FileHistoryId(org.syncany.database.PartialFileHistory.FileHistoryId) MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) VectorClock(org.syncany.database.VectorClock) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ChunkChecksum(org.syncany.database.ChunkEntry.ChunkChecksum) Date(java.util.Date) PartialFileHistory(org.syncany.database.PartialFileHistory) SAXException(org.xml.sax.SAXException) FileContent(org.syncany.database.FileContent) MultiChunkEntry(org.syncany.database.MultiChunkEntry) ChunkEntry(org.syncany.database.ChunkEntry) FileVersion(org.syncany.database.FileVersion) MultiChunkEntry(org.syncany.database.MultiChunkEntry) DatabaseVersion(org.syncany.database.DatabaseVersion)

Example 9 with MultiChunkEntry

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

the class MultiChunkSqlDao method createMultiChunkEntriesWithChunks.

private Map<MultiChunkId, MultiChunkEntry> createMultiChunkEntriesWithChunks(ResultSet resultSet) throws SQLException {
    Map<MultiChunkId, MultiChunkEntry> multiChunkEntries = new HashMap<MultiChunkId, MultiChunkEntry>();
    MultiChunkId currentMultiChunkId = null;
    while (resultSet.next()) {
        MultiChunkId multiChunkId = MultiChunkId.parseMultiChunkId(resultSet.getString("multichunk_id"));
        long multiChunkSize = resultSet.getLong("size");
        MultiChunkEntry multiChunkEntry = null;
        if (currentMultiChunkId != null && currentMultiChunkId.equals(multiChunkId)) {
            multiChunkEntry = multiChunkEntries.get(multiChunkId);
        } else {
            multiChunkEntry = new MultiChunkEntry(multiChunkId, multiChunkSize);
        }
        multiChunkEntry.addChunk(ChunkChecksum.parseChunkChecksum(resultSet.getString("chunk_checksum")));
        multiChunkEntries.put(multiChunkId, multiChunkEntry);
        currentMultiChunkId = multiChunkId;
    }
    return multiChunkEntries;
}
Also used : MultiChunkId(org.syncany.database.MultiChunkEntry.MultiChunkId) HashMap(java.util.HashMap) MultiChunkEntry(org.syncany.database.MultiChunkEntry)

Example 10 with MultiChunkEntry

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

the class CleanupOperation method deleteUnusedRemoteMultiChunks.

/**
 * This method adds unusedMultiChunks to the @{link RemoteTransaction} for deletion.
 *
 * @param unusedMultiChunks which are to be deleted because all references to them are gone.
 */
private void deleteUnusedRemoteMultiChunks(Map<MultiChunkId, MultiChunkEntry> unusedMultiChunks) throws StorageException {
    logger.log(Level.INFO, "- Deleting remote multichunks ...");
    for (MultiChunkEntry multiChunkEntry : unusedMultiChunks.values()) {
        logger.log(Level.FINE, "  + Deleting remote multichunk " + multiChunkEntry + " ...");
        remoteTransaction.delete(new MultichunkRemoteFile(multiChunkEntry.getId()));
    }
}
Also used : MultichunkRemoteFile(org.syncany.plugins.transfer.files.MultichunkRemoteFile) MultiChunkEntry(org.syncany.database.MultiChunkEntry)

Aggregations

MultiChunkEntry (org.syncany.database.MultiChunkEntry)17 MultiChunkId (org.syncany.database.MultiChunkEntry.MultiChunkId)12 DatabaseVersion (org.syncany.database.DatabaseVersion)7 Test (org.junit.Test)6 ChunkEntry (org.syncany.database.ChunkEntry)6 ChunkChecksum (org.syncany.database.ChunkEntry.ChunkChecksum)5 Connection (java.sql.Connection)4 Config (org.syncany.config.Config)4 FileContent (org.syncany.database.FileContent)4 MultiChunkSqlDao (org.syncany.database.dao.MultiChunkSqlDao)4 DatabaseVersionHeader (org.syncany.database.DatabaseVersionHeader)3 FileVersion (org.syncany.database.FileVersion)3 PartialFileHistory (org.syncany.database.PartialFileHistory)3 FileHistoryId (org.syncany.database.PartialFileHistory.FileHistoryId)3 PreparedStatement (java.sql.PreparedStatement)2 Date (java.util.Date)2 HashMap (java.util.HashMap)2 MemoryDatabase (org.syncany.database.MemoryDatabase)2 ChunkSqlDao (org.syncany.database.dao.ChunkSqlDao)2 DatabaseVersionSqlDao (org.syncany.database.dao.DatabaseVersionSqlDao)2