/* * Syncany, www.syncany.org * Copyright (C) 2011-2014 Philipp C. Heckel <philipp.heckel@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.syncany.database; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import org.syncany.config.Config; import org.syncany.database.ChunkEntry.ChunkChecksum; import org.syncany.database.FileContent.FileChecksum; import org.syncany.database.FileVersion.FileType; import org.syncany.database.MultiChunkEntry.MultiChunkId; import org.syncany.database.PartialFileHistory.FileHistoryId; import org.syncany.database.dao.ApplicationSqlDao; import org.syncany.database.dao.ChunkSqlDao; import org.syncany.database.dao.DatabaseVersionSqlDao; import org.syncany.database.dao.FileContentSqlDao; import org.syncany.database.dao.FileHistorySqlDao; import org.syncany.database.dao.FileVersionSqlDao; import org.syncany.database.dao.MultiChunkSqlDao; import org.syncany.operations.down.DatabaseBranch; import org.syncany.plugins.transfer.files.DatabaseRemoteFile; /** * Represents the single entry point for all SQL database queries. * * <p>This class combines all specific SQL database data access objects (DAOs) into * a single class, and forwards all method calls to the responsible DAO. * * @see {@link ApplicationSqlDao} * @see {@link ChunkSqlDao} * @see {@link FileContentSqlDao} * @see {@link FileVersionSqlDao} * @see {@link FileHistorySqlDao} * @see {@link MultiChunkSqlDao} * @see {@link DatabaseVersionSqlDao} * @author Philipp C. Heckel <philipp.heckel@gmail.com> */ public class SqlDatabase { protected static final Logger logger = Logger.getLogger(SqlDatabase.class.getSimpleName()); protected Connection connection; protected ApplicationSqlDao applicationDao; protected ChunkSqlDao chunkDao; protected FileContentSqlDao fileContentDao; protected FileVersionSqlDao fileVersionDao; protected FileHistorySqlDao fileHistoryDao; protected MultiChunkSqlDao multiChunkDao; protected DatabaseVersionSqlDao databaseVersionDao; public SqlDatabase(Config config) { this.connection = config.createDatabaseConnection(); this.applicationDao = new ApplicationSqlDao(connection); this.chunkDao = new ChunkSqlDao(connection); this.fileContentDao = new FileContentSqlDao(connection); this.fileVersionDao = new FileVersionSqlDao(connection); this.fileHistoryDao = new FileHistorySqlDao(connection, fileVersionDao); this.multiChunkDao = new MultiChunkSqlDao(connection); this.databaseVersionDao = new DatabaseVersionSqlDao(connection, chunkDao, fileContentDao, fileVersionDao, fileHistoryDao, multiChunkDao); } // General public Connection getConnection() { return connection; // TODO [low] Exposes internal state! } public void commit() throws SQLException { connection.commit(); } public void rollback() throws SQLException { connection.rollback(); } public void removeUnreferencedDatabaseEntities() { try { removeUnreferencedFileHistories(); removeUnreferencedFileContents(); removeUnreferencedMultiChunks(); removeUnreferencedChunks(); removeEmptyDatabaseVersionHeaders(); } catch (SQLException e) { throw new RuntimeException(e); } } // Application public void writeKnownRemoteDatabases(List<DatabaseRemoteFile> remoteDatabases) throws SQLException { applicationDao.writeKnownRemoteDatabases(remoteDatabases); } public List<DatabaseRemoteFile> getKnownDatabases() { return applicationDao.getKnownDatabases(); } public VectorClock getHighestKnownDatabaseFilenameNumbers() { return applicationDao.getHighestKnownDatabaseFilenameNumbers(); } public void removeKnownDatabases() { applicationDao.removeKnownDatabases(); } public Long getCleanupNumber() { return applicationDao.getCleanupNumber(); } public Long getCleanupTime() { return applicationDao.getCleanupTime(); } public void writeCleanupNumber(long cleanupNumber) { applicationDao.writeCleanupNumber(cleanupNumber); } public void writeCleanupTime(long cleanupTime) { applicationDao.writeCleanupTime(cleanupTime); } public void deleteAll() { applicationDao.deleteAll(); } public void shutdown() { applicationDao.shutdown(); } // Database version public Iterator<DatabaseVersion> getDirtyDatabaseVersions() { return databaseVersionDao.getDirtyDatabaseVersions(); } public Iterator<DatabaseVersion> getDatabaseVersionsTo(String machineName, long maxLocalClientVersion) { return databaseVersionDao.getDatabaseVersionsTo(machineName, maxLocalClientVersion); } public DatabaseVersionHeader getLastDatabaseVersionHeader() { return databaseVersionDao.getLastDatabaseVersionHeader(); } public DatabaseBranch getLocalDatabaseBranch() { return databaseVersionDao.getLocalDatabaseBranch(); } public List<DatabaseVersionHeader> getNonEmptyDatabaseVersionHeaders() { return databaseVersionDao.getNonEmptyDatabaseVersionHeaders(); } public long writeDatabaseVersion(DatabaseVersion databaseVersion) { return databaseVersionDao.writeDatabaseVersion(databaseVersion); } public void persistPurgeDatabaseVersion(DatabaseVersion purgeDatabaseVersion) { databaseVersionDao.writePurgeDatabaseVersion(purgeDatabaseVersion); } public void writeDatabaseVersionHeader(DatabaseVersionHeader databaseVersionHeader) throws SQLException { databaseVersionDao.writeDatabaseVersionHeader(databaseVersionHeader); } public void markDatabaseVersionDirty(VectorClock vectorClock) { databaseVersionDao.markDatabaseVersionDirty(vectorClock); } public void removeDirtyDatabaseVersions(long newDatabaseVersionId) { databaseVersionDao.removeDirtyDatabaseVersions(newDatabaseVersionId); } public void removeEmptyDatabaseVersionHeaders() { databaseVersionDao.removeEmptyDatabaseVersionHeaders(); } public Long getMaxDirtyVectorClock(String machineName) { return databaseVersionDao.getMaxDirtyVectorClock(machineName); } // File History @Deprecated public Map<FileHistoryId, PartialFileHistory> getFileHistoriesWithFileVersions() { // TODO [medium] Note: This returns the full database. Don't use this! return fileHistoryDao.getFileHistoriesWithFileVersions(); } public Map<FileHistoryId, PartialFileHistory> getFileHistories(List<FileHistoryId> fileHistoryIds) { return fileHistoryDao.getFileHistories(fileHistoryIds); } public List<PartialFileHistory> getFileHistoriesWithLastVersion() { return fileHistoryDao.getFileHistoriesWithLastVersion(); } private void removeUnreferencedFileHistories() throws SQLException { fileHistoryDao.removeUnreferencedFileHistories(); } public FileHistoryId expandFileHistoryId(FileHistoryId fileHistoryId) { return fileHistoryDao.expandFileHistoryId(fileHistoryId); } // File Version public Map<String, FileVersion> getCurrentFileTree() { return fileVersionDao.getCurrentFileTree(); } public Map<String, FileVersion> getCurrentFileTree(String prefix) { return fileVersionDao.getCurrentFileTree(prefix); } public void removeSmallerOrEqualFileVersions(Map<FileHistoryId, FileVersion> purgeFileVersions) throws SQLException { fileVersionDao.removeFileVersions(purgeFileVersions); } @Deprecated public FileVersion getFileVersionByPath(String path) { return fileVersionDao.getFileVersionByPath(path); } @Deprecated public Map<String, FileVersion> getFileTreeAtDate(Date date) { return fileVersionDao.getFileTreeAtDate(date); } public Map<String, FileVersion> getFileTree(String filter, Date date, boolean recursive, Set<FileType> fileTypes) { return fileVersionDao.getFileTree(filter, date, recursive, fileTypes); } public List<FileVersion> getFileHistory(FileHistoryId fileHistoryId) { return fileVersionDao.getFileHistory(fileHistoryId); } public Map<FileHistoryId, FileVersion> getFileHistoriesWithMaxPurgeVersion(int keepVersionsCount) { return fileVersionDao.getFileHistoriesWithMaxPurgeVersion(keepVersionsCount); } public Map<FileHistoryId, FileVersion> getDeletedFileVersions() { return fileVersionDao.getDeletedFileVersions(); } public FileVersion getFileVersion(FileHistoryId fileHistoryId, long version) { return fileVersionDao.getFileVersion(fileHistoryId, version); } // Multi Chunk public List<MultiChunkId> getMultiChunkIds(FileChecksum fileChecksum) { return multiChunkDao.getMultiChunkIds(fileChecksum); } public MultiChunkId getMultiChunkId(ChunkChecksum chunkChecksum) { return multiChunkDao.getMultiChunkId(chunkChecksum); } public Map<ChunkChecksum, MultiChunkId> getMultiChunkIdsByChecksums(List<ChunkChecksum> chunkChecksums) { return multiChunkDao.getMultiChunkIdsByChecksums(chunkChecksums); } public List<MultiChunkId> getDirtyMultiChunkIds() { return multiChunkDao.getDirtyMultiChunkIds(); } public Map<MultiChunkId, MultiChunkEntry> getUnusedMultiChunks() { return multiChunkDao.getUnusedMultiChunks(); } private void removeUnreferencedMultiChunks() throws SQLException { multiChunkDao.removeUnreferencedMultiChunks(); } public Map<MultiChunkId, MultiChunkEntry> getMultiChunks() { return multiChunkDao.getMultiChunks(); } public void writeMuddyMultiChunks(Map<DatabaseVersionHeader, Collection<MultiChunkEntry>> muddyMultiChunks) throws SQLException { multiChunkDao.writeMuddyMultiChunks(muddyMultiChunks); } public Map<MultiChunkId, MultiChunkEntry> getMuddyMultiChunks() { return multiChunkDao.getMuddyMultiChunks(); } public void removeNonMuddyMultiChunks() throws SQLException { multiChunkDao.removeNonMuddyMultiChunks(); } // Chunk protected Map<ChunkChecksum, ChunkEntry> getChunks(VectorClock vectorClock) { return chunkDao.getChunks(vectorClock); } public ChunkEntry getChunk(ChunkChecksum chunkChecksum) { return chunkDao.getChunk(chunkChecksum); } private void removeUnreferencedChunks() { chunkDao.removeUnreferencedChunks(); } // File Content public FileContent getFileContent(FileChecksum fileChecksum, boolean includeChunkChecksums) { return fileContentDao.getFileContent(fileChecksum, includeChunkChecksums); } private void removeUnreferencedFileContents() throws SQLException { fileContentDao.removeUnreferencedFileContents(); } }