/* * Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute * Copyright [2016-2017] EMBL-European Bioinformatics Institute * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * ChecksumDatabase * * @author dstaines * @author $Author$ * @version $Revision$ */ package org.ensembl.healthcheck.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.apache.commons.io.FileUtils; import org.ensembl.healthcheck.DatabaseRegistryEntry; /** * Utility to compare checksums from a set of database tables to a persistent * file on disk * * @author dstaines */ public class ChecksumDatabase { protected final static String CHECKSUM_SQL = "CHECKSUM TABLE %s EXTENDED"; protected final String databaseName; protected final SqlTemplate templ; protected final File checksumFile; protected final Collection<String> tables; public ChecksumDatabase(DatabaseRegistryEntry dbre, File directory, Collection<String> tables) { this(dbre.getName(), DBUtils.getSqlTemplate(dbre), directory, tables); } public ChecksumDatabase(DatabaseRegistryEntry dbre, Collection<String> tables) { this(dbre.getName(), DBUtils.getSqlTemplate(dbre), null, tables); } public ChecksumDatabase(String databaseName, SqlTemplate templ, File directory, Collection<String> tables) { this.databaseName = databaseName; this.templ = templ; this.tables = tables; if (directory==null) { checksumFile = null; } else { directory.mkdirs(); checksumFile = new File(directory, databaseName + ".chk"); } } protected Properties getChecksumFromFile() { Properties fileSum = new Properties(); if (checksumFile.exists()) { try { fileSum.load(new FileInputStream(checksumFile)); } catch (IOException e) { throw new RuntimeException("Cannot read table properties from " + checksumFile, e); } } return fileSum; } public Properties getChecksumFromDatabase() { Properties dbSum = new Properties(); for (final String table : tables) { dbSum.putAll(templ.queryForMap( CHECKSUM_SQL.replaceFirst("%s", table), new MapRowMapper<String, String>() { @Override public String mapRow(ResultSet resultSet, int position) throws SQLException { return resultSet.getString(2); } @Override public Map<String, String> getMap() { return CollectionUtils.createHashMap(1); } @Override public String getKey(ResultSet resultSet) throws SQLException { return resultSet.getString(1); } @Override public void existingObject(String currentValue, ResultSet resultSet, int position) throws SQLException { throw new RuntimeException(); } })); } return dbSum; } public boolean isUpdated() { boolean updated = false; Properties db = getChecksumFromDatabase(); Properties fs = getChecksumFromFile(); for (Entry<Object, Object> e : db.entrySet()) { Object fsVal = fs.get(e.getKey()); if (!e.getValue().equals(fsVal)) { updated = true; break; } } return updated; } public void setRead() { // Write properties file try { getChecksumFromDatabase().store(new FileOutputStream(checksumFile), null); } catch (IOException e) { throw new RuntimeException("Cannot write table properties to " + checksumFile, e); } } public void reset() { checksumFile.delete(); } }