package org.curiosity.management; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import org.curiosity.concept.Camera; import org.curiosity.concept.ResponseHeader; import org.curiosity.crawl.HeaderCrawler; import org.curiosity.util.DatabaseInvariants; import java.net.URL; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; /** * Detects and removes low-resolution images from the database. * * @author jherwitz */ public class ThumbnailGarbageCollector { private final static long fullSizeRequirement = 50000; private final HeaderCrawler crawler; private final Connection conn; public ThumbnailGarbageCollector(HeaderCrawler crawler, Connection conn) { this.crawler = Preconditions.checkNotNull(crawler); this.conn = Preconditions.checkNotNull(conn); } /** * GC all of {@code camera}'s low-resolution images from {@code startSol} onwards. */ public void sweep(int startSol, Camera camera) { /** * First: Pull list of urls to test. */ String sql = String.format("SELECT imageUrl FROM %s.%s WHERE sol >= %d", DatabaseInvariants.databaseName(), DatabaseInvariants.imageTableName(camera), startSol); List<URL> uris; try { PreparedStatement statement = conn.prepareStatement(sql); ResultSet resultSet = statement.executeQuery(); uris = parseResultSet(resultSet); statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } /** * Second: Get header for each uri. * If the content length is less than we require, remove the image from the database. */ uris.stream().forEach(uri -> { ResponseHeader header = crawler.crawl(uri); if (header.contentLength() < fullSizeRequirement) { System.out.printf("Removing url %s: content length %s < %s (threshold) \n", uri.toExternalForm(), header.contentLength(), fullSizeRequirement); try { removeFromDb(camera, uri); } catch (SQLException e) { throw new RuntimeException(e); } } }); } /** * Parse the database {@link ResultSet} for {@link URL}s to check. */ private List<URL> parseResultSet(ResultSet resultSet) throws SQLException { ImmutableList.Builder<URL> builder = ImmutableList.builder(); resultSet.first(); while (!resultSet.isAfterLast()) { builder.add(resultSet.getURL("imageUrl")); resultSet.next(); } return builder.build(); } /** * Remove {@code uri} from the database. */ private void removeFromDb(Camera camera, URL uri) throws SQLException { String sql = String.format("DELETE FROM %s.%s where imageUrl = \"%s\"", DatabaseInvariants.databaseName(), DatabaseInvariants.imageTableName(camera), uri.toExternalForm()); PreparedStatement statement = conn.prepareStatement(sql); statement.execute(); conn.commit(); statement.close(); } }