diff options
author | Simon Rettberg | 2015-08-18 15:04:17 +0200 |
---|---|---|
committer | Simon Rettberg | 2015-08-18 15:04:17 +0200 |
commit | c87ec3599fb22bd4b97d7ffbb7542fdbb22f3ca9 (patch) | |
tree | f7fe4d94708729459ae136fe2d981a0d8f6417d4 /dozentenmodulserver | |
parent | [client] Handle TTransferRejectedException in ThriftError.showMessage (diff) | |
download | tutor-module-c87ec3599fb22bd4b97d7ffbb7542fdbb22f3ca9.tar.gz tutor-module-c87ec3599fb22bd4b97d7ffbb7542fdbb22f3ca9.tar.xz tutor-module-c87ec3599fb22bd4b97d7ffbb7542fdbb22f3ca9.zip |
[server] Update lectures and images when image versions change or get deleted
Diffstat (limited to 'dozentenmodulserver')
6 files changed, 118 insertions, 35 deletions
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java index 261fbf5a..81898d7c 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java @@ -64,11 +64,12 @@ public class App { @Override public boolean thriftError(int failCount, String method, Throwable t) { - if (failCount > 2 || (t != null && !(t instanceof TTransportException))) { + if (failCount > 2 || t == null || !(t instanceof TTransportException)) { LOGGER.warn("Thrift Client error for " + method + ", FAIL."); return false; } - LOGGER.info("Thrift Client error for " + method + ", retrying..."); + LOGGER.info("Thrift transport error " + ((TTransportException) t).getType() + " for " + + method + ", retrying..."); try { Thread.sleep(failCount * 250); } catch (InterruptedException e) { diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlConnection.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlConnection.java index c17b7946..253d45f2 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlConnection.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/MysqlConnection.java @@ -51,6 +51,7 @@ public class MysqlConnection implements AutoCloseable { public void close() { if (hasPendingQueries) { LOGGER.warn("Mysql connection had uncommited queries on .close()"); + hasPendingQueries = false; } try { rawConnection.rollback(); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java index 605dff1a..a6b6d4b8 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java @@ -23,6 +23,8 @@ import org.openslx.bwlp.thrift.iface.ShareMode; import org.openslx.bwlp.thrift.iface.TNotFoundException; import org.openslx.bwlp.thrift.iface.UserInfo; import org.openslx.filetransfer.util.ChunkList; +import org.openslx.util.QuickTimer; +import org.openslx.util.QuickTimer.Task; public class DbImage { @@ -387,42 +389,18 @@ public class DbImage { */ public static void markForDeletion(String imageVersionId) throws SQLException, TNotFoundException { try (MysqlConnection connection = Database.getConnection()) { - // Determine new latest version, as we might have to update the imagebase and lecture tables - List<ImageVersionDetails> versions = DbImage.getImageVersions(connection, - DbImage.getBaseIdForVersionId(connection, imageVersionId)); - ImageVersionDetails newVersion = null; - ImageVersionDetails oldVersion = null; - for (ImageVersionDetails version : versions) { - if (version.versionId.equals(imageVersionId)) { - oldVersion = version; - } else if (version.isValid - && (newVersion == null || version.createTime > newVersion.createTime)) { - newVersion = version; - } - } - if (oldVersion == null) { - LOGGER.warn("BUG: old version ninja'd away on markForDeletion (" + imageVersionId + ")"); - throw new TNotFoundException(); - } // Disable version in question MysqlStatement disableStmt = connection.prepareStatement("UPDATE imageversion SET" + " expiretime = UNIX_TIMESTAMP() - 86400 * 5, isvalid = 0" + " WHERE imageversionid = :versionid"); disableStmt.setString("versionid", imageVersionId); disableStmt.executeUpdate(); - // Switch any lectures linking to this version - DbLecture.autoSwitchUsedImage(connection, oldVersion, newVersion); - // Now update the latestversionid of the baseimage if applicable - MysqlStatement latestStmt = connection.prepareStatement("UPDATE imagebase SET latestversionid = :newversionid" - + " WHERE latestversionid = :oldversionid"); - latestStmt.setString("newversionid", newVersion == null ? null : newVersion.versionId); - latestStmt.setString("oldversionid", oldVersion.versionId); - latestStmt.executeUpdate(); connection.commit(); } catch (SQLException e) { LOGGER.error("Query failed in DbImage.markForDeletion()", e); throw e; } + updateLatestVersionAsync(imageVersionId, null); } public static void setShareMode(String imageBaseId, ImageBaseWrite newData) throws SQLException { @@ -478,4 +456,81 @@ public class DbImage { } } + public static void markValid(LocalImageVersion imageVersion, boolean valid) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("UPDATE imageversion SET isvalid = :valid" + + " WHERE imageversionid = :imageversionid"); + stmt.setString("imageversionid", imageVersion.imageVersionId); + stmt.setBoolean("valid", valid); + stmt.executeUpdate(); + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbImage.markInvalid()", e); + throw e; + } + updateLatestVersionAsync(imageVersion.imageVersionId, imageVersion.imageBaseId); + } + + private static void updateLatestVersionAsync(final String changingImageVersionId, final String imageBaseId) { + QuickTimer.scheduleOnce(new Task() { + @Override + public void fire() { + try (MysqlConnection connection = Database.getConnection()) { + updateLatestVersion(connection, changingImageVersionId, imageBaseId); + connection.commit(); + } catch (SQLException | TNotFoundException e) { + LOGGER.error("Query failed in DbImage.updateLatestVersion()", e); + } + } + }); + } + + /** + * Makes sure the latestVersionId-field of the given base image is + * consistent, while also updating any affected lectures. + * + * @param connection mysql connection to use + * @param changingImageVersionId the version id of the image that changed + * (REQUIRED) + * @param imageBaseId the base id of the image that changed (OPTIONAL, will + * be determined if missing) + * @throws TNotFoundException + * @throws SQLException + */ + private static void updateLatestVersion(MysqlConnection connection, String changingImageVersionId, + String imageBaseId) throws TNotFoundException, SQLException { + if (imageBaseId == null) { + imageBaseId = DbImage.getBaseIdForVersionId(connection, changingImageVersionId); + if (imageBaseId == null) + throw new TNotFoundException(); + } + // Determine new latest version, as we might have to update the imagebase and lecture tables + List<ImageVersionDetails> versions = DbImage.getImageVersions(connection, imageBaseId); + ImageVersionDetails newVersion = null; + ImageVersionDetails oldVersion = null; + for (ImageVersionDetails version : versions) { + if (version.versionId.equals(changingImageVersionId)) { + oldVersion = version; + } + if (version.isValid && (newVersion == null || version.createTime > newVersion.createTime)) { + newVersion = version; + } + } + if (oldVersion == null) { + LOGGER.warn("BUG: oldVersion ninjad away on updateLatestVersion (" + changingImageVersionId + ")"); + } else { + // Switch any lectures linking to this version if applicable + if (oldVersion.isValid) { + DbLecture.autoUpdateUsedImage(connection, imageBaseId, newVersion.versionId); + } else { + DbLecture.forcefullySwitchUsedImage(connection, oldVersion, newVersion); + } + } + // Now update the latestversionid of the baseimage if applicable + MysqlStatement latestStmt = connection.prepareStatement("UPDATE imagebase SET latestversionid = :newversionid" + + " WHERE imagebaseid = :imagebaseid"); + latestStmt.setString("newversionid", newVersion == null ? null : newVersion.versionId); + latestStmt.setString("imagebaseid", imageBaseId); + latestStmt.executeUpdate(); + } } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java index cbc4c690..c44d40ed 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java @@ -308,6 +308,15 @@ public class DbLecture { return affected == 1; } + /** + * Called when a new version for an image is uploaded. Update all lectures + * using the same base image which have the autoUpdate-flag set. + * + * @param connection + * @param imageBaseId + * @param imageVersionId + * @throws SQLException + */ protected static void autoUpdateUsedImage(MysqlConnection connection, String imageBaseId, String imageVersionId) throws SQLException { // TODO: select first so we can email @@ -324,9 +333,12 @@ public class DbLecture { * Called when an image version is deleted or marked for deletion, so that * linking lectures switch over to other available versions. */ - protected static void autoSwitchUsedImage(MysqlConnection connection, ImageVersionDetails oldVersion, + protected static void forcefullySwitchUsedImage(MysqlConnection connection, ImageVersionDetails oldVersion, ImageVersionDetails newVersion) throws TNotFoundException, SQLException { - // First, get list of lectures using the image version to switch away to + if (oldVersion == newVersion + || (newVersion != null && newVersion.versionId.equals(oldVersion.versionId))) + return; + // First, get list of lectures using the image version to switch away from List<String> lectures = getAllUsingImageVersion(connection, oldVersion.versionId); if (lectures.isEmpty()) return; diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java index 3232374e..cc54ba94 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; +import java.sql.SQLException; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -16,6 +17,7 @@ import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.database.mappers.DbImage; import org.openslx.bwlp.sat.database.models.LocalImageVersion; import org.openslx.bwlp.sat.util.Configuration; import org.openslx.bwlp.sat.util.Constants; @@ -181,9 +183,22 @@ public class FileServer implements IncomingEvent { if (!srcFile.canRead()) { LOGGER.warn("Rejecting download of VID " + localImageData.imageVersionId + ": Missing " + srcFile.getPath()); - // TODO: Mark as invalid in DB + try { + DbImage.markValid(localImageData, false); + } catch (SQLException e) { + } throw new TTransferRejectedException("File missing on server"); } + if (srcFile.length() != localImageData.fileSize) { + LOGGER.warn("Rejecting download of VID " + localImageData.imageVersionId + ": Size mismatch for " + + srcFile.getPath() + " (expected " + localImageData.fileSize + ", is " + + srcFile.length() + ")"); + try { + DbImage.markValid(localImageData, false); + } catch (SQLException e) { + } + throw new TTransferRejectedException("File corrupted on server"); + } String key = UUID.randomUUID().toString(); ActiveDownload transfer = new ActiveDownload(key, srcFile); downloads.put(key, transfer); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java index 41d790bc..6e5e4d32 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java @@ -30,11 +30,11 @@ public class User { private static final LecturePermissions lectureNothing = new LecturePermissions(false, false); public static boolean isTutor(UserInfo user) { - return user.role == Role.TUTOR; + return user != null && user.role == Role.TUTOR; } public static boolean isStudent(UserInfo user) { - return user.role == Role.STUDENT; + return user != null && user.role == Role.STUDENT; } /** @@ -175,10 +175,9 @@ public class User { } catch (SQLException e) { throw new TInternalServerError(); } - if (user != null && user.role != Role.STUDENT) { - if (image.userPermissions.download) + if (image.userPermissions.download) { + if (isTutor(user)) return; - } else { // User is unknown role or student, check version's restricted flag for (ImageVersionDetails version : image.versions) { if (!version.isRestricted && version.versionId.equals(imageVersionId)) |