Skip to content
Snippets Groups Projects
Commit 254b87e2 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

Merge branch 'dev' into f-move

parents 8a7d617e 58bb48de
No related branches found
No related tags found
1 merge request!5ENH: treat case of removed files
Pipeline #5619 passed
......@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
* #122 - Dead-lock due to error in the DatabaseAccessManager.
* #120 - Editing entities that were created with a no longer existing user
leads to a server error.
* #31 - Queries with keywords in the path (e.g. `... STORED AT 0in.txt`)
......
......@@ -26,6 +26,7 @@
package org.caosdb.server.database;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import org.caosdb.server.database.access.Access;
import org.caosdb.server.database.access.AccessControlAccess;
......@@ -56,7 +57,7 @@ import org.caosdb.server.utils.Releasable;
class ReadAccessSemaphore extends Semaphore implements Releasable {
private static final long serialVersionUID = 4384921156838881337L;
private int acquired = 0; // how many threads have read access
private AtomicInteger acquired = new AtomicInteger(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.
......@@ -73,10 +74,9 @@ class ReadAccessSemaphore extends Semaphore implements Releasable {
@Override
public void acquire() throws InterruptedException {
super.acquire(); // Protect the next few lines
if (this.acquired == 0) {
if (this.acquired.getAndIncrement() == 0) {
this.writersBlock.acquire();
}
this.acquired++;
super.release();
}
......@@ -87,9 +87,7 @@ class ReadAccessSemaphore extends Semaphore implements Releasable {
*/
@Override
public void release() {
this.acquired--;
if (this.acquired <= 0) { // Last permit: release
this.acquired = 0;
if (this.acquired.decrementAndGet() == 0) { // Last permit: release
if (this.writersBlock.availablePermits() <= 0) {
this.writersBlock.release();
}
......
......@@ -22,10 +22,91 @@
*/
package org.caosdb.server.database;
import static org.junit.Assert.assertFalse;
import java.util.LinkedList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class DatabaseAccessManagerTest {
Thread createReadThread(long wait, String name, ReadAccessSemaphore readAccess) {
return new Thread(
new Runnable() {
@Override
public void run() {
try {
readAccess.acquire();
Thread.sleep(wait);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readAccess.release();
}
}
},
name);
}
Thread createWriteThread(long wait, String name, WriteAccessLock writeAccess) {
return new Thread(
new Runnable() {
@Override
public void run() {
try {
writeAccess.reserve();
Thread.sleep(wait);
writeAccess.lockInterruptibly();
Thread.sleep(wait);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
writeAccess.release();
}
}
},
name);
}
@Test
public void testDeadLock() throws InterruptedException {
final ReadAccessSemaphore readAccess = new ReadAccessSemaphore();
final WriteAccessLock writeAccess = new WriteAccessLock(readAccess);
List<Thread> ts = new LinkedList<>();
for (int i = 0; i < 1000; i++) {
Thread t1 = createReadThread(1, "Ra" + i, readAccess);
Thread t2 = createReadThread(2, "Rb" + i, readAccess);
Thread t3 = createReadThread(3, "Rc" + i, readAccess);
Thread t5 = createReadThread(5, "Rd" + i, readAccess);
Thread t7 = createReadThread(7, "Re" + i, readAccess);
Thread t11 = createReadThread(11, "Rf" + i, readAccess);
Thread w5 = createWriteThread(2, "W" + i, writeAccess);
t1.start();
t2.start();
w5.start();
t3.start();
t5.start();
t7.start();
t11.start();
ts.add(t1);
ts.add(t2);
ts.add(t3);
ts.add(t5);
ts.add(t7);
ts.add(t11);
ts.add(w5);
}
for (Thread t : ts) {
t.join(10000);
assertFalse(t.isAlive());
}
}
public static final ReadAccessSemaphore readAccess = new ReadAccessSemaphore();
public static final WriteAccessLock writeAccess = new WriteAccessLock(readAccess);
......
......@@ -70,8 +70,8 @@ public class QueryTest {
/**
* Assure that {@link WriteTransaction#commit()} calls {@link Query#clearCache()}.
*
* Since currently the cache shall be cleared whenever there is a commit.
* */
* <p>Since currently the cache shall be cleared whenever there is a commit.
*/
@Test
public void testEtagChangesAfterWrite() {
String old = Query.getETag();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment