aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/database/BaseObjectManager.java
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2020-02-22 11:34:57 -0800
committerAnton Tananaev <anton.tananaev@gmail.com>2020-02-22 11:34:57 -0800
commitdeb519ebd6798450509afaf4067e140edd7eb0d0 (patch)
treee93d94d51245355e2b43c3cb3aedc77e169f0f09 /src/main/java/org/traccar/database/BaseObjectManager.java
parentcb25fe3e58c0876fe6c000a1f0a7c7435e3fb0e1 (diff)
downloadtraccar-server-deb519ebd6798450509afaf4067e140edd7eb0d0.tar.gz
traccar-server-deb519ebd6798450509afaf4067e140edd7eb0d0.tar.bz2
traccar-server-deb519ebd6798450509afaf4067e140edd7eb0d0.zip
Fix concurrency issues
Diffstat (limited to 'src/main/java/org/traccar/database/BaseObjectManager.java')
-rw-r--r--src/main/java/org/traccar/database/BaseObjectManager.java60
1 files changed, 54 insertions, 6 deletions
diff --git a/src/main/java/org/traccar/database/BaseObjectManager.java b/src/main/java/org/traccar/database/BaseObjectManager.java
index 8bf9ef860..e274e5aba 100644
--- a/src/main/java/org/traccar/database/BaseObjectManager.java
+++ b/src/main/java/org/traccar/database/BaseObjectManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org)
* Copyright 2017 Andrey Kunitsyn (andrey@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +23,8 @@ import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +34,8 @@ public class BaseObjectManager<T extends BaseModel> {
private static final Logger LOGGER = LoggerFactory.getLogger(BaseObjectManager.class);
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
private final DataManager dataManager;
private Map<Long, T> items;
@@ -43,6 +47,22 @@ public class BaseObjectManager<T extends BaseModel> {
refreshItems();
}
+ protected final void readLock() {
+ lock.readLock().lock();
+ }
+
+ protected final void readUnlock() {
+ lock.readLock().unlock();
+ }
+
+ protected final void writeLock() {
+ lock.writeLock().lock();
+ }
+
+ protected final void writeUnlock() {
+ lock.writeLock().unlock();
+ }
+
protected final DataManager getDataManager() {
return dataManager;
}
@@ -52,12 +72,18 @@ public class BaseObjectManager<T extends BaseModel> {
}
public T getById(long itemId) {
- return items.get(itemId);
+ try {
+ readLock();
+ return items.get(itemId);
+ } finally {
+ readUnlock();
+ }
}
public void refreshItems() {
if (dataManager != null) {
try {
+ writeLock();
Collection<T> databaseItems = dataManager.getObjects(baseClass);
if (items == null) {
items = new ConcurrentHashMap<>(databaseItems.size());
@@ -78,12 +104,19 @@ public class BaseObjectManager<T extends BaseModel> {
}
} catch (SQLException error) {
LOGGER.warn("Error refreshing items", error);
+ } finally {
+ writeUnlock();
}
}
}
protected void addNewItem(T item) {
- items.put(item.getId(), item);
+ try {
+ writeLock();
+ items.put(item.getId(), item);
+ } finally {
+ writeUnlock();
+ }
}
public void addItem(T item) throws SQLException {
@@ -92,7 +125,12 @@ public class BaseObjectManager<T extends BaseModel> {
}
protected void updateCachedItem(T item) {
- items.put(item.getId(), item);
+ try {
+ writeLock();
+ items.put(item.getId(), item);
+ } finally {
+ writeUnlock();
+ }
}
public void updateItem(T item) throws SQLException {
@@ -101,7 +139,12 @@ public class BaseObjectManager<T extends BaseModel> {
}
protected void removeCachedItem(long itemId) {
- items.remove(itemId);
+ try {
+ writeLock();
+ items.remove(itemId);
+ } finally {
+ writeUnlock();
+ }
}
public void removeItem(long itemId) throws SQLException {
@@ -121,7 +164,12 @@ public class BaseObjectManager<T extends BaseModel> {
}
public Set<Long> getAllItems() {
- return items.keySet();
+ try {
+ readLock();
+ return items.keySet();
+ } finally {
+ readUnlock();
+ }
}
}