From 72b76510df0ea9646a8bde07cc462933123932eb Mon Sep 17 00:00:00 2001
From: Quazgar <quazgar@posteo.de>
Date: Tue, 25 Aug 2020 08:41:04 +0000
Subject: [PATCH] FIX: Forcing SRID initiation also for ChecksumUpdater

Necessary for bug #99.
---
 CHANGELOG.md                                  |  1 +
 .../server/database/BackendTransaction.java   |  2 ++
 .../server/database/MySQLSetFileChecksum.java | 31 +++++++++++++++++++
 .../interfaces/SetFileChecksumImpl.java       |  6 ++++
 .../backend/transaction/SetFileChecksum.java  | 26 ++++++++++++++++
 .../caosdb/server/entity/FileProperties.java  |  6 ++--
 .../server/transaction/ChecksumUpdater.java   |  6 ++--
 7 files changed, 73 insertions(+), 5 deletions(-)
 create mode 100644 src/main/java/caosdb/server/database/MySQLSetFileChecksum.java
 create mode 100644 src/main/java/caosdb/server/database/backend/interfaces/SetFileChecksumImpl.java
 create mode 100644 src/main/java/caosdb/server/database/backend/transaction/SetFileChecksum.java

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 613ee315..71e19edb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - #11 - pam_authentication leaks the password to unprivileged processes on the
   same machine.
 - #39 - quotes around datetimes in queries
+- #99 - Checksum updating resulted in infinite loop on server.
 
 ### Security (in case of vulnerabilities)
 
diff --git a/src/main/java/caosdb/server/database/BackendTransaction.java b/src/main/java/caosdb/server/database/BackendTransaction.java
index 55987005..c476fb5b 100644
--- a/src/main/java/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/caosdb/server/database/BackendTransaction.java
@@ -119,6 +119,7 @@ import caosdb.server.database.backend.interfaces.RetrieveUserImpl;
 import caosdb.server.database.backend.interfaces.RetrieveVersionHistoryImpl;
 import caosdb.server.database.backend.interfaces.RuleLoaderImpl;
 import caosdb.server.database.backend.interfaces.SetFileCheckedTimestampImpl;
+import caosdb.server.database.backend.interfaces.SetFileChecksumImpl;
 import caosdb.server.database.backend.interfaces.SetPasswordImpl;
 import caosdb.server.database.backend.interfaces.SetPermissionRulesImpl;
 import caosdb.server.database.backend.interfaces.SetQueryTemplateDefinitionImpl;
@@ -209,6 +210,7 @@ public abstract class BackendTransaction implements Undoable {
           RetrieveQueryTemplateDefinitionImpl.class, MySQLRetrieveQueryTemplateDefinition.class);
       setImpl(InsertEntityDatatypeImpl.class, MySQLInsertEntityDatatype.class);
       setImpl(RetrieveVersionHistoryImpl.class, MySQLRetrieveVersionHistory.class);
+      setImpl(SetFileChecksumImpl.class, MySQLSetFileChecksum.class);
     }
   }
 
diff --git a/src/main/java/caosdb/server/database/MySQLSetFileChecksum.java b/src/main/java/caosdb/server/database/MySQLSetFileChecksum.java
new file mode 100644
index 00000000..a74843b6
--- /dev/null
+++ b/src/main/java/caosdb/server/database/MySQLSetFileChecksum.java
@@ -0,0 +1,31 @@
+package caosdb.server.database;
+
+import caosdb.server.database.access.Access;
+import caosdb.server.database.backend.implementation.MySQL.ConnectionException;
+import caosdb.server.database.backend.implementation.MySQL.MySQLTransaction;
+import caosdb.server.database.backend.interfaces.SetFileChecksumImpl;
+import caosdb.server.database.exceptions.TransactionException;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+public class MySQLSetFileChecksum extends MySQLTransaction implements SetFileChecksumImpl {
+
+  public MySQLSetFileChecksum(Access access) {
+    super(access);
+  }
+
+  public static final String STMT_SET_CHECKSUM =
+      "UPDATE files SET hash = unhex(?) WHERE file_id = ?";
+
+  @Override
+  public void execute(Integer id, String checksum) {
+    try {
+      PreparedStatement stmt = prepareStatement(STMT_SET_CHECKSUM);
+      stmt.setInt(2, id);
+      stmt.setString(1, checksum);
+      stmt.execute();
+    } catch (SQLException | ConnectionException e) {
+      throw new TransactionException(e);
+    }
+  }
+}
diff --git a/src/main/java/caosdb/server/database/backend/interfaces/SetFileChecksumImpl.java b/src/main/java/caosdb/server/database/backend/interfaces/SetFileChecksumImpl.java
new file mode 100644
index 00000000..be73b33e
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/interfaces/SetFileChecksumImpl.java
@@ -0,0 +1,6 @@
+package caosdb.server.database.backend.interfaces;
+
+public interface SetFileChecksumImpl extends BackendTransactionImpl {
+
+  void execute(Integer id, String checksum);
+}
diff --git a/src/main/java/caosdb/server/database/backend/transaction/SetFileChecksum.java b/src/main/java/caosdb/server/database/backend/transaction/SetFileChecksum.java
new file mode 100644
index 00000000..b19bceab
--- /dev/null
+++ b/src/main/java/caosdb/server/database/backend/transaction/SetFileChecksum.java
@@ -0,0 +1,26 @@
+package caosdb.server.database.backend.transaction;
+
+import caosdb.server.database.BackendTransaction;
+import caosdb.server.database.backend.interfaces.SetFileChecksumImpl;
+import caosdb.server.entity.EntityInterface;
+
+public class SetFileChecksum extends BackendTransaction {
+
+  private EntityInterface entity;
+
+  public SetFileChecksum(EntityInterface entity) {
+    this.entity = entity;
+  }
+
+  @Override
+  protected void execute() {
+    RetrieveSparseEntity.removeCached(this.entity);
+    if (entity.hasFileProperties()) {
+      GetFileRecordByPath.removeCached(this.entity.getFileProperties().getPath());
+
+      final SetFileChecksumImpl t = getImplementation(SetFileChecksumImpl.class);
+
+      t.execute(this.entity.getId(), this.entity.getFileProperties().getChecksum());
+    }
+  }
+}
diff --git a/src/main/java/caosdb/server/entity/FileProperties.java b/src/main/java/caosdb/server/entity/FileProperties.java
index fbf8031f..c0fcaa46 100644
--- a/src/main/java/caosdb/server/entity/FileProperties.java
+++ b/src/main/java/caosdb/server/entity/FileProperties.java
@@ -220,10 +220,10 @@ public class FileProperties {
     if (file.getAbsolutePath().startsWith(FileSystem.getBasepath())) {
       final Undoable d;
       final File parent = file.getParentFile();
-      if (file.getCanonicalPath().startsWith(FileSystem.getBasepath())) {
-        d = FileUtils.delete(file, file.isDirectory());
-      } else if (FileUtils.isSymlink(file)) {
+      if (FileUtils.isSymlink(file)) {
         d = FileUtils.unlink(file);
+      } else if (file.getCanonicalPath().startsWith(FileSystem.getBasepath())) {
+        d = FileUtils.delete(file, file.isDirectory());
       } else {
         throw new CaosDBException(
             "File is in Filesystem, but it is neither a normal file nor a symlink.");
diff --git a/src/main/java/caosdb/server/transaction/ChecksumUpdater.java b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java
index 29603fc5..ec923bec 100644
--- a/src/main/java/caosdb/server/transaction/ChecksumUpdater.java
+++ b/src/main/java/caosdb/server/transaction/ChecksumUpdater.java
@@ -27,7 +27,7 @@ import caosdb.server.database.DatabaseMonitor;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.transaction.GetUpdateableChecksums;
 import caosdb.server.database.backend.transaction.RetrieveSparseEntity;
-import caosdb.server.database.backend.transaction.UpdateSparseEntity;
+import caosdb.server.database.backend.transaction.SetFileChecksum;
 import caosdb.server.database.exceptions.TransactionException;
 import caosdb.server.entity.EntityInterface;
 import caosdb.server.entity.FileProperties;
@@ -46,6 +46,7 @@ import java.security.NoSuchAlgorithmException;
 public class ChecksumUpdater extends WriteTransaction<TransactionContainer> implements Runnable {
 
   private Boolean running = false;
+
   private static final ChecksumUpdater instance = new ChecksumUpdater();
 
   private ChecksumUpdater() {
@@ -85,7 +86,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl
           DatabaseMonitor.getInstance().acquireStrongAccess(this);
 
           // update
-          execute(new UpdateSparseEntity(fileEntity), strongAccess);
+          execute(new SetFileChecksum(fileEntity), strongAccess);
           strongAccess.commit();
 
         } catch (final InterruptedException e) {
@@ -145,6 +146,7 @@ public class ChecksumUpdater extends WriteTransaction<TransactionContainer> impl
       }
     } catch (final Exception e) {
       e.printStackTrace();
+      instance.running = false;
       return null;
     } finally {
       weakAccess.release();
-- 
GitLab