diff --git a/CHANGELOG.md b/CHANGELOG.md
index 00be947d7..ec3443aaf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Naksha_2.1.5
+
+- Fixed thread hanging issue fixed by avoiding indefinite locking in `FibLinearProbeTable.java`
+
## Naksha_2.1.4
- Fixes:
diff --git a/gradle.properties b/gradle.properties
index b8604b519..9b66cc554 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -11,4 +11,4 @@ mavenPassword=YourPassword
# - here-naksha-lib-core/NakshaVersion (static property: latest)
# - here-naksha-lib-psql/resources/naksha_plpgsql.sql (method: naksha_version)
# - here-naksha-app-service/src/main/resources/swagger/openapi.yaml (info.version property)
-version=2.1.4
+version=2.1.5
diff --git a/here-naksha-app-service/src/main/resources/swagger/openapi.yaml b/here-naksha-app-service/src/main/resources/swagger/openapi.yaml
index d7f80dce9..f3b01152a 100644
--- a/here-naksha-app-service/src/main/resources/swagger/openapi.yaml
+++ b/here-naksha-app-service/src/main/resources/swagger/openapi.yaml
@@ -12,7 +12,7 @@ servers:
info:
title: "Naksha Hub-API"
description: "Naksha Hub-API is a REST API to provide simple access to geo data."
- version: "2.1.4"
+ version: "2.1.5"
security:
- AccessToken: [ ]
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/AbstractTask.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/AbstractTask.java
index b0c7c7503..949eb0476 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/AbstractTask.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/AbstractTask.java
@@ -613,6 +613,9 @@ private void incInstanceLevelUsage(String actorId, long limit) {
break;
}
// Failed, conflict, repeat
+ log.info(
+ "Concurrency conflict while incrementing instance level threadCount from {}. Will retry...",
+ threadCount);
}
}
@@ -649,6 +652,9 @@ private void incActorLevelUsage(String actorId, long limit) {
if (counter == null) {
Long existing = actorUsageMap.putIfAbsent(actorId, 1L);
if (existing != null) {
+ log.info(
+ "Concurrency conflict while initializing threadCount to 1 for actorId [{}]. Will retry...",
+ actorId);
continue; // Repeat, conflict with other thread
}
return;
@@ -669,6 +675,10 @@ private void incActorLevelUsage(String actorId, long limit) {
break;
}
// Failed, conflict, repeat
+ log.info(
+ "Concurrency conflict while incrementing actor level threadCount from {} for actorId [{}]. Will retry...",
+ counter,
+ actorId);
}
}
@@ -693,6 +703,9 @@ private void decActorLevelUsage(String actorId) {
log.error("Invalid actor usage value for actor: " + actorId + " value: " + current);
}
if (!actorUsageMap.remove(actorId, current)) {
+ log.info(
+ "Concurrency conflict while removing actor level threadCount for actorId [{}]. Will retry...",
+ actorId);
continue;
}
break;
@@ -700,6 +713,10 @@ private void decActorLevelUsage(String actorId) {
break;
}
// Failed, repeat, conflict with other thread
+ log.info(
+ "Concurrency conflict while decrementing actor level threadCount from {} for actorId [{}]. Will retry...",
+ current,
+ actorId);
}
}
}
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/NakshaContext.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/NakshaContext.java
index d1302cd25..ff3062dcb 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/NakshaContext.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/NakshaContext.java
@@ -221,6 +221,7 @@ public long startNanos() {
return newValue;
}
// Conflict, two threads seem to want to update the same key the same time!
+ logger.info("Concurrency conflict while updating attachment map for key {}", valueClass);
}
}
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/storage/IStorage.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/storage/IStorage.java
index f0313a810..c0043bc84 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/storage/IStorage.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/storage/IStorage.java
@@ -32,6 +32,8 @@
import org.jetbrains.annotations.ApiStatus.AvailableSince;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Storage API to gain access to storages.
@@ -39,6 +41,8 @@
@AvailableSince(NakshaVersion.v2_0_6)
public interface IStorage extends AutoCloseable {
+ Logger logger = LoggerFactory.getLogger(IStorage.class);
+
/**
* Initializes the storage, create the transaction table, install needed scripts and extensions.
*
@@ -191,10 +195,12 @@ default void close() {
try {
shutdown(null).get();
return;
- } catch (InterruptedException ignore) {
+ } catch (InterruptedException ie) {
+ logger.warn("Exception while shutting down IStorage. ", ie);
} catch (Exception e) {
throw unchecked(e);
}
+ logger.info("Unable to shutdown IStorage. Will retry...");
}
}
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/FibMap.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/FibMap.java
index 904298d01..444fbbd96 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/FibMap.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/FibMap.java
@@ -29,6 +29,8 @@
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Functional implementation of a recursive, thread safe, growing map, based upon ) {
Reference> ref = (Reference>) raw;
entry = (ENTRY) ref.get();
- if (entry == null && lock.tryLock()) {
+ if (entry == null && (lock.isHeldByCurrentThread() || lock.tryLock())) {
locked = true;
array[i] = null;
SIZE.getAndAdd(fibSet, -1L);
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/fib/FibSet.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/fib/FibSet.java
index 7033ad47c..928e31af1 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/fib/FibSet.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/fib/FibSet.java
@@ -37,6 +37,8 @@
import org.jetbrains.annotations.ApiStatus.AvailableSince;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A recursive, thread safe, weak/soft/strong referencing set, based upon > {
+ private static final Logger logger = LoggerFactory.getLogger(FibSet.class);
+
/**
* The empty array used by default, so that empty maps do not consume memory.
*/
@@ -452,6 +456,9 @@ ENTRY _execute(
if (raw_entry == null) {
if (!ARRAY.compareAndSet(array, index, ref, null)) {
// Race condition, another thread modified the array slot.
+ logger.info(
+ "Concurrency conflict while initializing array value at index {}. Will retry...",
+ index);
continue;
}
SIZE.getAndAdd(this, -1L);
@@ -487,6 +494,7 @@ ENTRY _execute(
return (ENTRY) entry;
}
// Race condition, other thread updated the reference concurrently.
+ logger.info("Concurrency conflict while setting array value at index {}. Will retry...", index);
continue;
}
assert op == REMOVE;
@@ -495,6 +503,7 @@ ENTRY _execute(
return (ENTRY) entry;
}
// Race condition, other thread updated the reference concurrently.
+ logger.info("Concurrency conflict while nullifying array value at index {}. Will retry...", index);
continue;
}
@@ -516,6 +525,7 @@ ENTRY _execute(
return _execute(op, key, key_hash, refType, sub_array, depth + 1);
}
// Race condition, another thread modified concurrently.
+ logger.info("Concurrency conflict while setting array value at index {}. Will retry...", index);
continue;
}
@@ -529,6 +539,7 @@ ENTRY _execute(
return new_entry;
}
// Race condition, another thread modified concurrently.
+ logger.info("Concurrency conflict while setting array value at index {}. Will retry...", index);
continue;
}
@@ -546,6 +557,7 @@ ENTRY _execute(
return new_entry;
}
// Race condition, another thread modified concurrently.
+ logger.info("Concurrency conflict while initializing array value at index {}. Will retry...", index);
}
}
diff --git a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/json/JsonFieldBool.java b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/json/JsonFieldBool.java
index f0a96c6c5..61e056c75 100644
--- a/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/json/JsonFieldBool.java
+++ b/here-naksha-lib-core/src/main/java/com/here/naksha/lib/core/util/json/JsonFieldBool.java
@@ -23,9 +23,13 @@
import java.nio.ByteOrder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public final class JsonFieldBool