Enable repo implementations to save storage. (#675)

* Enable repo implementations to save storage.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Cleanup.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2018-05-04 09:31:57 +02:00
committed by GitHub
parent 6dd98d2134
commit b715fb5798
3 changed files with 78 additions and 66 deletions

73
.gitignore vendored
View File

@@ -1,61 +1,56 @@
# Directories # # Directories #
/build/ build
/*/build/ bin
/bin/ tmp
/*/bin/ .settings
/target/ .classpath
/*/target/ target
/*/*/target/ .allure
.vscode
.springbeans
.metadata
.project
# OS Files # # Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
# OSX
.DS_Store .DS_Store
.svn
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Compiled filed
*.class *.class
# Package Files # # Package Files #
*.jar *.jar
*.war *.war
*.ear
*.db
# Sonar # Sonar
.sonar_lock .sonar_lock
# VSCode
classpath-data.json
# Created by spring-boot-configuration-processor # Created by spring-boot-configuration-processor
.factorypath .factorypath
# Eclipse IDE # Eclipse IDE
*.pydevproject *.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# IDEA
*.iml
.idea
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
# Maven # Maven
maven.properties maven.properties
/*/maven.properties
hawkbit-repository/hawkbit-repository-jpa/.springBeans # Test Files
*.tmp

View File

@@ -67,7 +67,9 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository {
@Override @Override
protected AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16, protected AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
final String contentType, final File file) throws IOException { final String contentType, final String tempFile) throws IOException {
final File file = new File(tempFile);
return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, sha1Hash16, return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, sha1Hash16,
new DbArtifactHash(sha1Hash16, mdMD5Hash16), file.length(), contentType)); new DbArtifactHash(sha1Hash16, mdMD5Hash16), file.length(), contentType));
} }

View File

@@ -10,11 +10,11 @@ package org.eclipse.hawkbit.artifact.repository;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.DigestOutputStream; import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@@ -22,6 +22,7 @@ import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
@@ -31,7 +32,6 @@ import com.google.common.io.ByteStreams;
* functionality, e.g. computation of hashes. * functionality, e.g. computation of hashes.
*/ */
public abstract class AbstractArtifactRepository implements ArtifactRepository { public abstract class AbstractArtifactRepository implements ArtifactRepository {
private static final String TEMP_FILE_PREFIX = "tmp"; private static final String TEMP_FILE_PREFIX = "tmp";
private static final String TEMP_FILE_SUFFIX = "artifactrepo"; private static final String TEMP_FILE_SUFFIX = "artifactrepo";
@@ -52,30 +52,54 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
throw new ArtifactStoreException(e.getMessage(), e); throw new ArtifactStoreException(e.getMessage(), e);
} }
LOG.debug("Creating temporary file and store the inputstream to it"); String tempFile = null;
try (final DigestInputStream inputstream = wrapInDigestInputStream(content, mdSHA1, mdMD5)) {
final File file = createTempFile(); tempFile = storeTempFile(inputstream);
try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) {
ByteStreams.copy(content, outputstream);
outputstream.flush();
final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest()); final String sha1Hash16 = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest()); final String md5Hash16 = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
LOG.debug("Temporary file {} stored. Calculated sha1: {} and md5: {} hashes", file, sha1Hash16, md5Hash16);
checkHashes(sha1Hash16, md5Hash16, hash); checkHashes(sha1Hash16, md5Hash16, hash);
return store(sanitizeTenant(tenant), sha1Hash16, md5Hash16, contentType, file); return store(sanitizeTenant(tenant), sha1Hash16, md5Hash16, contentType, tempFile);
} catch (final IOException e) { } catch (final IOException e) {
throw new ArtifactStoreException(e.getMessage(), e); throw new ArtifactStoreException(e.getMessage(), e);
} finally { } finally {
if (file != null && file.exists() && !file.delete()) { if (!StringUtils.isEmpty(tempFile)) {
LOG.error("Could not delete temp file {}", file); deleteTempFile(tempFile);
} }
} }
} }
protected void deleteTempFile(final String tempFile) {
final File file = new File(tempFile);
if (file.exists() && !file.delete()) {
LOG.error("Could not delete temp file {}", file);
}
}
protected String storeTempFile(final InputStream content) throws IOException {
final File file = createTempFile();
try (final OutputStream outputstream = new BufferedOutputStream(new FileOutputStream(file))) {
ByteStreams.copy(content, outputstream);
outputstream.flush();
}
return file.getPath();
}
private static File createTempFile() {
try {
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
} catch (final IOException e) {
throw new ArtifactStoreException("Cannot create tempfile", e);
}
}
private static void checkHashes(final String sha1Hash16, final String md5Hash16, final DbArtifactHash hash) { private static void checkHashes(final String sha1Hash16, final String md5Hash16, final DbArtifactHash hash) {
if (hash == null) { if (hash == null) {
return; return;
@@ -92,20 +116,11 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository {
} }
protected abstract AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16, protected abstract AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
final String contentType, final File file) throws IOException; final String contentType, final String tempFile) throws IOException;
private static File createTempFile() { private static DigestInputStream wrapInDigestInputStream(final InputStream input, final MessageDigest mdSHA1,
try { final MessageDigest mdMD5) {
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX); return new DigestInputStream(new DigestInputStream(input, mdMD5), mdSHA1);
} catch (final IOException e) {
throw new ArtifactStoreException("Cannot create tempfile", e);
}
}
private static DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1,
final MessageDigest mdMD5) throws FileNotFoundException {
return new DigestOutputStream(
new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1);
} }
protected static String sanitizeTenant(final String tenant) { protected static String sanitizeTenant(final String tenant) {