From 1019930229be1c1c750d8dae1e2d606cb50e09ce Mon Sep 17 00:00:00 2001
From: Daniel Hornung <d.hornung@indiscale.com>
Date: Wed, 10 Feb 2021 09:50:26 +0100
Subject: [PATCH] DOC STY: Some documentation, typos, ...

---
 CHANGELOG.md                                  |   2 +
 .../java/org/caosdb/server/CaosDBServer.java  |   6 +-
 .../server/database/BackendTransaction.java   |   2 +-
 .../database/DatabaseAccessManager.java       | 142 +++++++++++-------
 .../entity/container/WritableContainer.java   |   2 +
 .../server/jobs/core/InsertFilesInDir.java    |   2 +
 .../server/transaction/WriteTransaction.java  |  19 ++-
 .../org/caosdb/server/utils/EntityStatus.java |  33 ++--
 8 files changed, 132 insertions(+), 76 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c862661..4bbc6cfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Removed
 
+* Text user interface (CaosDBTerminal).
+
 ### Fixed
 
 * Bug: When the user password is updated the user is deactivated.
diff --git a/src/main/java/org/caosdb/server/CaosDBServer.java b/src/main/java/org/caosdb/server/CaosDBServer.java
index 82d79177..4a69f24d 100644
--- a/src/main/java/org/caosdb/server/CaosDBServer.java
+++ b/src/main/java/org/caosdb/server/CaosDBServer.java
@@ -159,8 +159,10 @@ public class CaosDBServer extends Application {
   /**
    * Parse the command line arguments.
    *
-   * <p>- "nobackend": flag to run caosdb without any backend (for testing purposes) - "insecure":
-   * flag to start only a http server (no https server)
+   * <ul>
+   *   <li>"nobackend": flag to run caosdb without any backend (for testing purposes)
+   *   <li>"insecure": flag to start only a http server (no https server)
+   * </ul>
    *
    * <p>Both flags are only available in the debug mode which is controlled by the `caosdb.debug`
    * JVM Property.
diff --git a/src/main/java/org/caosdb/server/database/BackendTransaction.java b/src/main/java/org/caosdb/server/database/BackendTransaction.java
index edf9b16f..61aebf42 100644
--- a/src/main/java/org/caosdb/server/database/BackendTransaction.java
+++ b/src/main/java/org/caosdb/server/database/BackendTransaction.java
@@ -298,7 +298,7 @@ public abstract class BackendTransaction implements Undoable {
     }
   }
 
-  /** Returns the type of transaction of an entity, e.g. "Retrieve" for a {@link RetrieveEntity}. */
+  /** Return the type of transaction of an entity, e.g. "Retrieve" for a {@link RetrieveEntity}. */
   public String getTransactionType(EntityInterface e) {
     return e.getClass().getSimpleName().replace("Entity", "");
   }
diff --git a/src/main/java/org/caosdb/server/database/DatabaseAccessManager.java b/src/main/java/org/caosdb/server/database/DatabaseAccessManager.java
index de468545..72710daf 100644
--- a/src/main/java/org/caosdb/server/database/DatabaseAccessManager.java
+++ b/src/main/java/org/caosdb/server/database/DatabaseAccessManager.java
@@ -4,6 +4,9 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2021 Indiscale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2021 Daniel Hornung <d.hornung@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -39,10 +42,10 @@ import org.caosdb.server.utils.Releasable;
 /**
  * Acquire and release read access. DatabaseMonitor uses this class for managing access to entities
  * during processing updates, inserts, deletions and retrievals. Read access will be granted
- * immediately for every thread that requests it, unless one or more threads requested for blocking
- * the read access (usually due to requesting for write access). If this happens, all threads that
- * already have read access will proceed and release their read access as usual but no NEW permits
- * will be granted.
+ * immediately for every thread that requests it, unless a thread requests that read access be
+ * blocked (usually by requesting write access). If this happens, all threads that already have read
+ * access will proceed and release their read access as usual but no NEW read permits will be
+ * granted.
  *
  * <p>This is a blockable {@link Semaphore}. Any number of threads may acquire a permit unless it is
  * blocked. The blocking thread (requesting a {@link WriteAccessLock}) waits until all threads have
@@ -53,8 +56,10 @@ import org.caosdb.server.utils.Releasable;
 class ReadAccessSemaphore extends Semaphore implements Releasable {
 
   private static final long serialVersionUID = 4384921156838881337L;
-  private int acquired = 0; // how many thread have read access
-  Semaphore block = new Semaphore(1, true);
+  private int acquired = 0; // how many threads have read access
+  Semaphore writersBlock =
+      new Semaphore(1, true); // This semaphore is blocked as long as there are any
+  // unreleased read permits.
 
   public ReadAccessSemaphore() {
     // this is a fair semaphore with no initial permit.
@@ -62,55 +67,65 @@ class ReadAccessSemaphore extends Semaphore implements Releasable {
   }
 
   /**
-   * Acquires a read access permit if and only if it has not been blocked via block(). If the
-   * ReadAccess is currently blocked, the thread wait until the unblock() method is invoked by any
-   * thread.
+   * Acquire a read access permit if and only if it has not been blocked via block(). If read access
+   * is currently blocked, the thread waits until the unblock() method is invoked by any thread.
    */
   @Override
   public void acquire() throws InterruptedException {
-    super.acquire();
+    super.acquire(); // Protect the next few lines
     if (this.acquired == 0) {
-      this.block.acquire();
+      this.writersBlock.acquire();
     }
     this.acquired++;
-    //    notifyObservers(null);
     super.release();
   }
 
-  /** Releases a read access permit. */
+  /**
+   * Release a read access permit.
+   *
+   * <p>If this is the last remaining acquired permit, also release the general writersBlock.
+   */
   @Override
   public void release() {
     this.acquired--;
-    if (this.acquired <= 0) {
+    if (this.acquired <= 0) { // Last permit: release
       this.acquired = 0;
-      if (this.block.availablePermits() <= 0) {
-        this.block.release();
+      if (this.writersBlock.availablePermits() <= 0) {
+        this.writersBlock.release();
       }
     }
   }
 
   /**
-   * Acquires the permit of a block of read access if no thread currently has a read access and no
-   * thread currently has a block. I.e. it blocks the further permission of read access for any
-   * thread. Every thread that has a read access yet can proceed. The current thread waits until any
-   * thread has released its read access. If another thread has invoked this method yet the current
-   * thread waits until the unblock() method is called.
+   * Acquire the permit to block further read access, if no thread currently has acquired read
+   * access and no thread currently has a block.
+   *
+   * <p>Consequences of calling this method are:
+   *
+   * <ul>
+   *   <li>Further read access permits are blocked for any thread.
+   *   <li>Every thread that has a read access already can proceed. The current thread waits until
+   *       all threads have released their read access.
+   * </ul>
+   *
+   * <p>If another thread has invoked this method before, the current thread waits until the
+   * unblock() method is called.
    *
    * @throws InterruptedException
    */
   public void block() throws InterruptedException {
     super.reducePermits(1);
-    this.block.acquire();
+    this.writersBlock.acquire();
   }
 
   /**
    * Unblock read access.
    *
-   * @throws InterruptedException
+   * <p>This method releases the writersBlock introduced by calling the block() method.
    */
   public void unblock() {
-    if (this.block.availablePermits() <= 0) {
-      this.block.release();
+    if (this.writersBlock.availablePermits() <= 0) {
+      this.writersBlock.release();
     }
     super.release();
   }
@@ -121,29 +136,47 @@ class ReadAccessSemaphore extends Semaphore implements Releasable {
 }
 
 /**
- * Acquire and release write access. DatabaseMonitor uses this class for managing access to entities
- * during processing updates, inserts, deletions and retrievals. Write access will be granted to one
- * and only one thread if no other thread yet holds read or write access permits. The write access
- * has to be allocated before requesting it to be permitted. See below.
+ * Acquire and release write access. DatabaseAccessManager uses this class for managing access to
+ * entities while processing updates, inserts, deletions and retrievals. Write access will be
+ * granted to one and only one thread if no other thread already holds read or write access permits.
+ * The write access seat has to be reserved before acquiring the lock.
+ *
+ * <p>The flow is as follows:
+ *
+ * <p>
+ *
+ * <pre>
+ *                                        No new read
+ *                                      access possible,
+ *    Read access      Read access    wait for running read
+ *      possible        possible       threads to fininish
+ *
+ *      +------+       +----------+       +----------+
+ * +--> |  no  | ----> | reserved | ----> | acquired | --+
+ * |    | Lock |       +----------+       +----------+   |
+ * |    +------+                 \          /            |
+ * |                           (1 seat together)         |
+ * +-----------------------------------------------------+
+ *             release()
+ * </pre>
  *
  * @author Timm Fitschen
  */
 class WriteAccessLock extends ReentrantLock implements Releasable {
 
-  private static final long serialVersionUID = -262226321839837533L;
-  private ReadAccessSemaphore wa = null;
+  private static final long serialVersionUID = 833147084787201103L;
+  private ReadAccessSemaphore readSem = null;
   private Thread reservedBy = null;
-  //  private Thread acquiredBy = null;
 
-  public WriteAccessLock(final ReadAccessSemaphore wa) {
+  public WriteAccessLock(final ReadAccessSemaphore readSem) {
     super();
-    this.wa = wa;
+    this.readSem = readSem;
   }
 
   /**
-   * Reserve the write access. While a write access is reserved but not yet acquired any read access
-   * may still be granted. When a write access is yet granted or another reservation is still
-   * active, the thread waits until the write access has been released.
+   * Reserve the seat for the next write access. While a write access is reserved but not yet
+   * acquired, all read access may still be granted. When a write access has been already granted or
+   * another reservation is active, the thread waits until the write access has been released.
    *
    * @throws InterruptedException
    */
@@ -152,18 +185,22 @@ class WriteAccessLock extends ReentrantLock implements Releasable {
     this.reservedBy = Thread.currentThread();
   }
 
+  /**
+   * Lock the write access seat. This method returns once all current read permits have been
+   * released.
+   */
   @Override
   public void lockInterruptibly() throws InterruptedException {
     if (!super.isHeldByCurrentThread()) {
       super.lock();
     }
-    this.wa.block();
+    this.readSem.block(); // Wait until all current read permits have been released.
   }
 
   @Override
   public void unlock() {
     if (super.isHeldByCurrentThread()) {
-      this.wa.unblock();
+      this.readSem.unblock();
       this.reservedBy = null;
       super.unlock();
     }
@@ -207,14 +244,14 @@ public class DatabaseAccessManager {
   }
 
   /**
-   * Acquire read access. This method returns the Access object as soon as there is no write access
-   * acquired.
+   * Acquire read access. This method returns the Access object as soon as there are no active write
+   * permits.
    *
    * <p>The returned Access object can be used to read in the data base back-end.
    *
-   * <p>Read access can be acquired parallel to other threads having read access or while other
-   * thread only reserved write access. As soon as any thread has requested to acquire write access,
-   * all other threads have to wait.
+   * <p>Read access can be acquired parallel to other threads having read access or while another
+   * thread has <em>reserved</em> write access. As soon as any thread has requested to
+   * <em>acquire</em> write access, all other threads have to wait.
    *
    * @param t the {@link TransactionInterface} which requests the read access
    * @return {@link Access} object which holds and abstract away all connection details.
@@ -226,16 +263,13 @@ public class DatabaseAccessManager {
   }
 
   /**
-   * Reserve write access. This method returns the Access object as soon as there is no other thread
-   * which reserved or acquired the write access. Otherwise this thread waits in the queue until it
-   * can reserve the write access.
+   * Reserve write access. This method returns the Access object as soon as there is no other
+   * reserved or acquired write access.
    *
    * <p>The returned Access object can be used to read in the data base back-end.
    *
-   * <p>While a write access is reserved but not yet acquired any read access may still be granted.
-   * When a write access is yet granted or another reservation is still active, no read or write
-   * accesses can be granted and all other thread have to waits until this write access has been
-   * released.
+   * <p>The reservation has no effect on granting of read access permits, but only one thread may at
+   * any time reserve or acquire write access.
    *
    * @param wt - the {@link WriteTransactionInterface} which request the reservation of the write
    *     access.
@@ -248,9 +282,9 @@ public class DatabaseAccessManager {
   }
 
   /**
-   * Acquire write access. This method returns the Access object ass soon as all already acquired
-   * read accesses have been released. When the write access is acquired, no other access can be
-   * acquired (read or write).
+   * Acquire write access. This method returns the Access object as soon as all already acquired
+   * read access permits have been released. When the write access is acquired, no other access can
+   * be acquired (read or write).
    *
    * <p>The returned Access object can be used to read and write in the data base back-end.
    *
diff --git a/src/main/java/org/caosdb/server/entity/container/WritableContainer.java b/src/main/java/org/caosdb/server/entity/container/WritableContainer.java
index 3b440569..5fdb8c39 100644
--- a/src/main/java/org/caosdb/server/entity/container/WritableContainer.java
+++ b/src/main/java/org/caosdb/server/entity/container/WritableContainer.java
@@ -4,6 +4,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2021 Indiscale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
diff --git a/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java b/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
index 4aedc0cb..52d46a37 100644
--- a/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
+++ b/src/main/java/org/caosdb/server/jobs/core/InsertFilesInDir.java
@@ -4,6 +4,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2021 Indiscale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
diff --git a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
index c54eb6f7..0f1fd21b 100644
--- a/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/WriteTransaction.java
@@ -4,8 +4,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -60,7 +60,7 @@ import org.caosdb.server.utils.ServerMessages;
  * This class is responsible for inserting, updating and deleting entities which are held in the
  * {@link TransactionContainer}.
  *
- * <p>This class initializes and run the {@link Schedule} of {@link Job}s, calls the {@link
+ * <p>This class initializes and runs the {@link Schedule} of {@link Job}s, calls the {@link
  * BackendTransaction}s for each entity, and handles exceptions, roll-back (if necessary) and clean
  * up afterwards.
  *
@@ -150,17 +150,15 @@ public class WriteTransaction extends Transaction<WritableContainer>
       }
     }
 
-    // allocate strong (write) access. Only one thread can do this
-    // at a time. But weak access can still be acquired by other
-    // thread until the allocated strong access is actually
-    // acquired.
+    // Reserve write access. Only one thread can do this at a time. But read access can still be
+    // acquired by other threads until the reserved write access is actually acquired.
     setAccess(getAccessManager().reserveWriteAccess(this));
 
-    // retrieve a container which contains all id of those entities
+    // Retrieve a container which contains all IDs of those entities
     // which are to be updated.
     execute(new RetrieveFullEntityTransaction(oldContainer), getAccess());
 
-    // retrieve all entity which are to be deleted.
+    // Retrieve all entities which are to be deleted.
     execute(new RetrieveFullEntityTransaction(deleteContainer), getAccess());
 
     // Check if any updates are to be processed.
@@ -282,7 +280,8 @@ public class WriteTransaction extends Transaction<WritableContainer>
   }
 
   /** Check if the user has all permissions */
-  public void checkPermissions(final EntityInterface entity, final Set<Permission> permissions) {
+  public static void checkPermissions(
+      final EntityInterface entity, final Set<Permission> permissions) {
     for (final Permission p : permissions) {
       entity.checkPermission(p);
     }
diff --git a/src/main/java/org/caosdb/server/utils/EntityStatus.java b/src/main/java/org/caosdb/server/utils/EntityStatus.java
index ef8bdc10..6687622c 100644
--- a/src/main/java/org/caosdb/server/utils/EntityStatus.java
+++ b/src/main/java/org/caosdb/server/utils/EntityStatus.java
@@ -4,6 +4,8 @@
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2021 Indiscale GmbH <info@indiscale.com>
+ * Copyright (C) 2021 Daniel Hornung <d.hornung@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -23,18 +25,31 @@
 package org.caosdb.server.utils;
 
 /**
- * IGNORE - This instance must be ignored during further processing. <br>
- * VALID - This instance has a final ID and has been synchronized with the database. <br>
- * WRITTEN - This instance has been written successfully to the database. It has a final ID. <br>
- * QUALIFIED - This instance has a provisional or final ID, represents a well-formed entity, and any
- * referenced entities (by a reference property) have status QUALIFIED or VALID. QUALIFIED - This
- * instance has been checked and is not qualified to be processed further (i.e. to be inserted,
- * updated, deleted) DELETED - This instance has been deleted recently. CORRUPT - This instance has
- * been retrieved from the database, but though something turned out to be wrong with it.
- * NONEXISTENT - This instance has been called (via id or something) but it doesn't exist.
+ * The order of the EntityStatus values matters, in that everything later than "QUALIFIED" also
+ * counts as qualified.
+ *
+ * <p>
+ *
+ * <ul>
+ *   <li>IGNORE - This instance must be ignored during further processing.
+ *   <li>UNQUALIFIED - This instance has been checked and is not qualified to be processed further
+ *       (i.e. to be inserted, updated, deleted)
+ *   <li>DELETED - This instance has been deleted recently.
+ *   <li>NONEXISTENT - This instance has been called (via id or something) but it doesn't exist.
+ *   <li>QUALIFIED - This instance has a provisional or final ID, represents a well-formed entity,
+ *       and any referenced entities (by a reference property) have status QUALIFIED or VALID. Every
+ *       status after this one also counts as QUALIFIED.
+ *   <li>VALID - This instance has a final ID and has been synchronized with the database.
+ * </ul>
  *
  * @author Timm Fitschen
  */
+
+// TODO Can these comment lines be removed?
+//  * <li>WRITTEN - This instance has been written successfully to the database. It has a final ID.
+//  * //  * <li>CORRUPT - This instance has
+//  * been retrieved from the database, but though something turned out to be wrong with it.
+
 public enum EntityStatus {
   IGNORE,
   UNQUALIFIED,
-- 
GitLab