aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbyss777 <abyss@fox5.ru>2016-07-15 15:33:08 +0500
committerAbyss777 <abyss@fox5.ru>2016-07-15 15:33:08 +0500
commitd71210f1f408c757d4fe3da07829bbc3362a7e93 (patch)
treed5c3a2c5e6856cc3bd145d5030b9acec7184acda
parent1f411961db56f7024d3e88cfaef89f1ab26fc9f1 (diff)
downloadtraccar-server-d71210f1f408c757d4fe3da07829bbc3362a7e93.tar.gz
traccar-server-d71210f1f408c757d4fe3da07829bbc3362a7e93.tar.bz2
traccar-server-d71210f1f408c757d4fe3da07829bbc3362a7e93.zip
Move code related to devices to DeviceManager
-rw-r--r--src/org/traccar/BaseProtocolDecoder.java6
-rw-r--r--src/org/traccar/Context.java17
-rw-r--r--src/org/traccar/DefaultDataHandler.java5
-rw-r--r--src/org/traccar/DistanceHandler.java4
-rw-r--r--src/org/traccar/FilterHandler.java4
-rw-r--r--src/org/traccar/MainEventHandler.java7
-rw-r--r--src/org/traccar/api/AsyncSocket.java2
-rw-r--r--src/org/traccar/api/resource/DeviceResource.java10
-rw-r--r--src/org/traccar/api/resource/PositionResource.java2
-rw-r--r--src/org/traccar/database/ConnectionManager.java72
-rw-r--r--src/org/traccar/database/DataManager.java133
-rw-r--r--src/org/traccar/database/DeviceManager.java261
-rw-r--r--src/org/traccar/database/GeofenceManager.java4
-rw-r--r--src/org/traccar/database/IdentityManager.java3
-rw-r--r--src/org/traccar/database/PermissionsManager.java2
-rw-r--r--src/org/traccar/events/GeofenceEventHandler.java2
-rw-r--r--src/org/traccar/events/MotionEventHandler.java23
-rw-r--r--src/org/traccar/events/OverspeedEventHandler.java2
-rw-r--r--test/org/traccar/ProtocolTest.java5
19 files changed, 342 insertions, 222 deletions
diff --git a/src/org/traccar/BaseProtocolDecoder.java b/src/org/traccar/BaseProtocolDecoder.java
index 3429f41f0..9a253e351 100644
--- a/src/org/traccar/BaseProtocolDecoder.java
+++ b/src/org/traccar/BaseProtocolDecoder.java
@@ -47,7 +47,9 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
Device device = Context.getIdentityManager().getDeviceByUniqueId(uniqueId);
if (device != null) {
deviceId = device.getId();
- Context.getConnectionManager().addActiveDevice(deviceId, protocol, channel, remoteAddress);
+ if (Context.getConnectionManager() != null) {
+ Context.getConnectionManager().addActiveDevice(deviceId, protocol, channel, remoteAddress);
+ }
return true;
} else {
deviceId = 0;
@@ -78,7 +80,7 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder {
public void getLastLocation(Position position, Date deviceTime) {
position.setOutdated(true);
- Position last = Context.getConnectionManager().getLastPosition(getDeviceId());
+ Position last = Context.getIdentityManager().getLastPosition(getDeviceId());
if (last != null) {
position.setFixTime(last.getFixTime());
position.setValid(last.getValid());
diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java
index 0bb18b675..d32837755 100644
--- a/src/org/traccar/Context.java
+++ b/src/org/traccar/Context.java
@@ -18,6 +18,7 @@ package org.traccar;
import com.ning.http.client.AsyncHttpClient;
import org.traccar.database.ConnectionManager;
import org.traccar.database.DataManager;
+import org.traccar.database.DeviceManager;
import org.traccar.database.IdentityManager;
import org.traccar.database.NotificationManager;
import org.traccar.database.PermissionsManager;
@@ -67,6 +68,12 @@ public final class Context {
return dataManager;
}
+ private static DeviceManager deviceManager;
+
+ public static DeviceManager getDeviceManager() {
+ return deviceManager;
+ }
+
private static ConnectionManager connectionManager;
public static ConnectionManager getConnectionManager() {
@@ -142,7 +149,12 @@ public final class Context {
if (config.hasKey("database.url")) {
dataManager = new DataManager(config);
}
- identityManager = dataManager;
+
+ if (dataManager != null) {
+ deviceManager = new DeviceManager(dataManager);
+ }
+
+ identityManager = deviceManager;
if (config.getBoolean("geocoder.enable")) {
String type = config.getString("geocoder.type", "google");
@@ -205,7 +217,7 @@ public final class Context {
permissionsManager = new PermissionsManager(dataManager);
- connectionManager = new ConnectionManager(dataManager);
+ connectionManager = new ConnectionManager();
if (config.getBoolean("event.geofenceHandler")) {
geofenceManager = new GeofenceManager(dataManager);
@@ -225,7 +237,6 @@ public final class Context {
public static void init(IdentityManager testIdentityManager) {
config = new Config();
- connectionManager = new ConnectionManager(null);
identityManager = testIdentityManager;
}
diff --git a/src/org/traccar/DefaultDataHandler.java b/src/org/traccar/DefaultDataHandler.java
index 594961389..8923c3a0e 100644
--- a/src/org/traccar/DefaultDataHandler.java
+++ b/src/org/traccar/DefaultDataHandler.java
@@ -25,10 +25,7 @@ public class DefaultDataHandler extends BaseDataHandler {
try {
Context.getDataManager().addPosition(position);
- Position lastPosition = Context.getConnectionManager().getLastPosition(position.getDeviceId());
- if (lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) > 0) {
- Context.getDataManager().updateLatestPosition(position);
- }
+ Context.getDeviceManager().updateLatestPosition(position);
} catch (Exception error) {
Log.warning(error);
}
diff --git a/src/org/traccar/DistanceHandler.java b/src/org/traccar/DistanceHandler.java
index b22815033..9f174a6c7 100644
--- a/src/org/traccar/DistanceHandler.java
+++ b/src/org/traccar/DistanceHandler.java
@@ -25,8 +25,8 @@ import java.math.RoundingMode;
public class DistanceHandler extends BaseDataHandler {
private Position getLastPosition(long deviceId) {
- if (Context.getConnectionManager() != null) {
- return Context.getConnectionManager().getLastPosition(deviceId);
+ if (Context.getIdentityManager() != null) {
+ return Context.getIdentityManager().getLastPosition(deviceId);
}
return null;
}
diff --git a/src/org/traccar/FilterHandler.java b/src/org/traccar/FilterHandler.java
index ab570ee26..5315bad9e 100644
--- a/src/org/traccar/FilterHandler.java
+++ b/src/org/traccar/FilterHandler.java
@@ -57,8 +57,8 @@ public class FilterHandler extends BaseDataHandler {
}
private Position getLastPosition(long deviceId) {
- if (Context.getConnectionManager() != null) {
- return Context.getConnectionManager().getLastPosition(deviceId);
+ if (Context.getIdentityManager() != null) {
+ return Context.getIdentityManager().getLastPosition(deviceId);
}
return null;
}
diff --git a/src/org/traccar/MainEventHandler.java b/src/org/traccar/MainEventHandler.java
index a0df34de5..771009aca 100644
--- a/src/org/traccar/MainEventHandler.java
+++ b/src/org/traccar/MainEventHandler.java
@@ -37,7 +37,7 @@ public class MainEventHandler extends IdleStateAwareChannelHandler {
Position position = (Position) e.getMessage();
- String uniqueId = Context.getDataManager().getDeviceById(position.getDeviceId()).getUniqueId();
+ String uniqueId = Context.getIdentityManager().getDeviceById(position.getDeviceId()).getUniqueId();
// Log position
StringBuilder s = new StringBuilder();
@@ -54,11 +54,6 @@ public class MainEventHandler extends IdleStateAwareChannelHandler {
s.append(", result: ").append(cmdResult);
}
Log.info(s.toString());
-
- Position lastPosition = Context.getConnectionManager().getLastPosition(position.getDeviceId());
- if (lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) > 0) {
- Context.getConnectionManager().updatePosition(position);
- }
}
}
diff --git a/src/org/traccar/api/AsyncSocket.java b/src/org/traccar/api/AsyncSocket.java
index d1e5594f4..4422dbccd 100644
--- a/src/org/traccar/api/AsyncSocket.java
+++ b/src/org/traccar/api/AsyncSocket.java
@@ -48,7 +48,7 @@ public class AsyncSocket extends WebSocketAdapter implements ConnectionManager.U
super.onWebSocketConnect(session);
Map<String, Collection<?>> data = new HashMap<>();
- data.put(KEY_POSITIONS, Context.getConnectionManager().getInitialState(userId));
+ data.put(KEY_POSITIONS, Context.getDeviceManager().getInitialState(userId));
sendData(data);
Context.getConnectionManager().addListener(userId, this);
diff --git a/src/org/traccar/api/resource/DeviceResource.java b/src/org/traccar/api/resource/DeviceResource.java
index d6c53dc04..f48df7553 100644
--- a/src/org/traccar/api/resource/DeviceResource.java
+++ b/src/org/traccar/api/resource/DeviceResource.java
@@ -44,20 +44,20 @@ public class DeviceResource extends BaseResource {
@QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException {
if (all) {
Context.getPermissionsManager().checkAdmin(getUserId());
- return Context.getDataManager().getAllDevicesCached();
+ return Context.getDeviceManager().getAllDevices();
} else {
if (userId == 0) {
userId = getUserId();
}
Context.getPermissionsManager().checkUser(getUserId(), userId);
- return Context.getDataManager().getDevices(userId);
+ return Context.getDeviceManager().getDevices(userId);
}
}
@POST
public Response add(Device entity) throws SQLException {
Context.getPermissionsManager().checkReadonly(getUserId());
- Context.getDataManager().addDevice(entity);
+ Context.getDeviceManager().addDevice(entity);
Context.getDataManager().linkDevice(getUserId(), entity.getId());
Context.getPermissionsManager().refresh();
if (Context.getGeofenceManager() != null) {
@@ -71,7 +71,7 @@ public class DeviceResource extends BaseResource {
public Response update(@PathParam("id") long id, Device entity) throws SQLException {
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), id);
- Context.getDataManager().updateDevice(entity);
+ Context.getDeviceManager().updateDevice(entity);
if (Context.getGeofenceManager() != null) {
Context.getGeofenceManager().refresh();
}
@@ -83,7 +83,7 @@ public class DeviceResource extends BaseResource {
public Response remove(@PathParam("id") long id) throws SQLException {
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), id);
- Context.getDataManager().removeDevice(id);
+ Context.getDeviceManager().removeDevice(id);
Context.getPermissionsManager().refresh();
if (Context.getGeofenceManager() != null) {
Context.getGeofenceManager().refresh();
diff --git a/src/org/traccar/api/resource/PositionResource.java b/src/org/traccar/api/resource/PositionResource.java
index 2da517d4f..e00e06e7a 100644
--- a/src/org/traccar/api/resource/PositionResource.java
+++ b/src/org/traccar/api/resource/PositionResource.java
@@ -39,7 +39,7 @@ public class PositionResource extends BaseResource {
@QueryParam("deviceId") long deviceId, @QueryParam("from") String from, @QueryParam("to") String to)
throws SQLException {
if (deviceId == 0) {
- return Context.getConnectionManager().getInitialState(getUserId());
+ return Context.getDeviceManager().getInitialState(getUserId());
} else {
Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
return Context.getDataManager().getPositions(
diff --git a/src/org/traccar/database/ConnectionManager.java b/src/org/traccar/database/ConnectionManager.java
index 8796673b1..46ccab81e 100644
--- a/src/org/traccar/database/ConnectionManager.java
+++ b/src/org/traccar/database/ConnectionManager.java
@@ -28,12 +28,9 @@ import org.traccar.model.Position;
import java.net.SocketAddress;
import java.sql.SQLException;
-import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -45,21 +42,11 @@ public class ConnectionManager {
private final long deviceTimeout;
private final Map<Long, ActiveDevice> activeDevices = new HashMap<>();
- private final Map<Long, Position> positions = new HashMap<>();
private final Map<Long, Set<UpdateListener>> listeners = new HashMap<>();
private final Map<Long, Timeout> timeouts = new HashMap<>();
- public ConnectionManager(DataManager dataManager) {
+ public ConnectionManager() {
deviceTimeout = Context.getConfig().getLong("status.timeout", DEFAULT_TIMEOUT) * 1000;
- if (dataManager != null) {
- try {
- for (Position position : dataManager.getLatestPositions()) {
- positions.put(position.getDeviceId(), position);
- }
- } catch (SQLException error) {
- Log.warning(error);
- }
- }
}
public void addActiveDevice(long deviceId, Protocol protocol, Channel channel, SocketAddress remoteAddress) {
@@ -80,31 +67,28 @@ public class ConnectionManager {
return activeDevices.get(deviceId);
}
- public synchronized void updateDevice(final long deviceId, String status, Date time) {
+ public void updateDevice(final long deviceId, String status, Date time) {
Device device = Context.getIdentityManager().getDeviceById(deviceId);
if (device == null) {
return;
}
- if (status.equals(Device.STATUS_MOVING) || status.equals(Device.STATUS_STOPPED)) {
- device.setMotion(status);
- } else {
- if (!status.equals(device.getStatus())) {
- Event event = new Event(Event.TYPE_DEVICE_OFFLINE, deviceId);
- if (status.equals(Device.STATUS_ONLINE)) {
- event.setType(Event.TYPE_DEVICE_ONLINE);
- }
- if (Context.getNotificationManager() != null) {
- Context.getNotificationManager().updateEvent(event, null);
- }
+ if (!status.equals(device.getStatus())) {
+ Event event = new Event(Event.TYPE_DEVICE_OFFLINE, deviceId);
+ if (status.equals(Device.STATUS_ONLINE)) {
+ event.setType(Event.TYPE_DEVICE_ONLINE);
}
- device.setStatus(status);
-
- Timeout timeout = timeouts.remove(deviceId);
- if (timeout != null) {
- timeout.cancel();
+ if (Context.getNotificationManager() != null) {
+ Context.getNotificationManager().updateEvent(event, null);
}
}
+ device.setStatus(status);
+
+ Timeout timeout = timeouts.remove(deviceId);
+ if (timeout != null) {
+ timeout.cancel();
+ }
+
if (time != null) {
device.setLastUpdate(time);
@@ -122,12 +106,16 @@ public class ConnectionManager {
}
try {
- Context.getDataManager().updateDeviceStatus(device);
+ Context.getDeviceManager().updateDeviceStatus(device);
} catch (SQLException error) {
Log.warning(error);
}
- for (long userId : Context.getPermissionsManager().getDeviceUsers(deviceId)) {
+ updateDevice(device);
+ }
+
+ public synchronized void updateDevice(Device device) {
+ for (long userId : Context.getPermissionsManager().getDeviceUsers(device.getId())) {
if (listeners.containsKey(userId)) {
for (UpdateListener listener : listeners.get(userId)) {
listener.onUpdateDevice(device);
@@ -138,7 +126,6 @@ public class ConnectionManager {
public synchronized void updatePosition(Position position) {
long deviceId = position.getDeviceId();
- positions.put(deviceId, position);
for (long userId : Context.getPermissionsManager().getDeviceUsers(deviceId)) {
if (listeners.containsKey(userId)) {
@@ -157,23 +144,6 @@ public class ConnectionManager {
}
}
- public Position getLastPosition(long deviceId) {
- return positions.get(deviceId);
- }
-
- public synchronized Collection<Position> getInitialState(long userId) {
-
- List<Position> result = new LinkedList<>();
-
- for (long deviceId : Context.getPermissionsManager().getDevicePermissions(userId)) {
- if (positions.containsKey(deviceId)) {
- result.add(positions.get(deviceId));
- }
- }
-
- return result;
- }
-
public interface UpdateListener {
void onUpdateDevice(Device device);
void onUpdatePosition(Position position);
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index 0dc3c5c52..0aecaf2e7 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -62,9 +62,9 @@ import org.traccar.model.GeofencePermission;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
-public class DataManager implements IdentityManager {
+public class DataManager {
- private static final long DEFAULT_REFRESH_DELAY = 300;
+ public static final long DEFAULT_REFRESH_DELAY = 300;
private final Config config;
@@ -72,11 +72,6 @@ public class DataManager implements IdentityManager {
private final long dataRefreshDelay;
- private final ReadWriteLock devicesLock = new ReentrantReadWriteLock();
- private final Map<Long, Device> devicesById = new HashMap<>();
- private final Map<String, Device> devicesByUniqueId = new HashMap<>();
- private long devicesLastUpdate;
-
private final ReadWriteLock groupsLock = new ReentrantReadWriteLock();
private final Map<Long, Group> groupsById = new HashMap<>();
private long groupsLastUpdate;
@@ -136,85 +131,6 @@ public class DataManager implements IdentityManager {
}
}
- private void updateDeviceCache(boolean force) throws SQLException {
- boolean needWrite;
- devicesLock.readLock().lock();
- try {
- needWrite = force || System.currentTimeMillis() - devicesLastUpdate > dataRefreshDelay;
- } finally {
- devicesLock.readLock().unlock();
- }
-
- if (needWrite) {
- devicesLock.writeLock().lock();
- try {
- if (force || System.currentTimeMillis() - devicesLastUpdate > dataRefreshDelay) {
- devicesById.clear();
- devicesByUniqueId.clear();
- ConnectionManager connectionManager = Context.getConnectionManager();
- GeofenceManager geofenceManager = Context.getGeofenceManager();
- for (Device device : getAllDevices()) {
- devicesById.put(device.getId(), device);
- devicesByUniqueId.put(device.getUniqueId(), device);
- if (connectionManager != null && geofenceManager != null) {
- Position lastPosition = connectionManager.getLastPosition(device.getId());
- if (lastPosition != null) {
- device.setGeofenceIds(geofenceManager.getCurrentDeviceGeofences(lastPosition));
- }
- }
- }
- devicesLastUpdate = System.currentTimeMillis();
- }
- } finally {
- devicesLock.writeLock().unlock();
- }
- }
- }
-
- @Override
- public Device getDeviceById(long id) {
- boolean forceUpdate;
- devicesLock.readLock().lock();
- try {
- forceUpdate = !devicesById.containsKey(id);
- } finally {
- devicesLock.readLock().unlock();
- }
-
- try {
- updateDeviceCache(forceUpdate);
- } catch (SQLException e) {
- Log.warning(e);
- }
-
- devicesLock.readLock().lock();
- try {
- return devicesById.get(id);
- } finally {
- devicesLock.readLock().unlock();
- }
- }
-
- @Override
- public Device getDeviceByUniqueId(String uniqueId) throws SQLException {
- boolean forceUpdate;
- devicesLock.readLock().lock();
- try {
- forceUpdate = !devicesByUniqueId.containsKey(uniqueId) && !config.getBoolean("database.ignoreUnknown");
- } finally {
- devicesLock.readLock().unlock();
- }
-
- updateDeviceCache(forceUpdate);
-
- devicesLock.readLock().lock();
- try {
- return devicesByUniqueId.get(uniqueId);
- } finally {
- devicesLock.readLock().unlock();
- }
- }
-
private void updateGroupCache(boolean force) throws SQLException {
boolean needWrite;
groupsLock.readLock().lock();
@@ -347,72 +263,33 @@ public class DataManager implements IdentityManager {
.executeQuery(GroupPermission.class);
}
- private Collection<Device> getAllDevices() throws SQLException {
+ public Collection<Device> getAllDevices() throws SQLException {
return QueryBuilder.create(dataSource, getQuery("database.selectDevicesAll"))
.executeQuery(Device.class);
}
- public Collection<Device> getAllDevicesCached() {
- boolean forceUpdate;
- devicesLock.readLock().lock();
- try {
- forceUpdate = devicesById.isEmpty();
- } finally {
- devicesLock.readLock().unlock();
- }
-
- try {
- updateDeviceCache(forceUpdate);
- } catch (SQLException e) {
- Log.warning(e);
- }
-
- devicesLock.readLock().lock();
- try {
- return devicesById.values();
- } finally {
- devicesLock.readLock().unlock();
- }
- }
-
- public Collection<Device> getDevices(long userId) throws SQLException {
- Collection<Device> devices = new ArrayList<>();
- for (long id : Context.getPermissionsManager().getDevicePermissions(userId)) {
- devices.add(getDeviceById(id));
- }
- return devices;
- }
-
public void addDevice(Device device) throws SQLException {
device.setId(QueryBuilder.create(dataSource, getQuery("database.insertDevice"), true)
.setObject(device)
.executeUpdate());
- updateDeviceCache(true);
}
public void updateDevice(Device device) throws SQLException {
QueryBuilder.create(dataSource, getQuery("database.updateDevice"))
.setObject(device)
.executeUpdate();
- updateDeviceCache(true);
}
public void updateDeviceStatus(Device device) throws SQLException {
QueryBuilder.create(dataSource, getQuery("database.updateDeviceStatus"))
.setObject(device)
.executeUpdate();
- if (devicesById.containsKey(device.getId())) {
- Device cachedDevice = devicesById.get(device.getId());
- cachedDevice.setStatus(device.getStatus());
- cachedDevice.setMotion(device.getMotion());
- }
}
public void removeDevice(long deviceId) throws SQLException {
QueryBuilder.create(dataSource, getQuery("database.deleteDevice"))
.setLong("id", deviceId)
.executeUpdate();
- updateDeviceCache(true);
}
public void linkDevice(long userId, long deviceId) throws SQLException {
@@ -514,10 +391,6 @@ public class DataManager implements IdentityManager {
.setDate("now", new Date())
.setObject(position)
.executeUpdate();
- if (devicesById.containsKey(position.getDeviceId())) {
- Device cachedDevice = devicesById.get(position.getDeviceId());
- cachedDevice.setPositionId(position.getId());
- }
}
public Collection<Position> getLatestPositions() throws SQLException {
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
new file mode 100644
index 000000000..70df1cc1a
--- /dev/null
+++ b/src/org/traccar/database/DeviceManager.java
@@ -0,0 +1,261 @@
+package org.traccar.database;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.traccar.Config;
+import org.traccar.Context;
+import org.traccar.helper.Log;
+import org.traccar.model.Device;
+import org.traccar.model.Position;
+
+public class DeviceManager implements IdentityManager {
+
+ private final Config config;
+ private final DataManager dataManager;
+ private final long dataRefreshDelay;
+
+ private final ReadWriteLock devicesLock = new ReentrantReadWriteLock();
+ private final Map<Long, Device> devicesById = new HashMap<>();
+ private final Map<String, Device> devicesByUniqueId = new HashMap<>();
+ private long devicesLastUpdate;
+
+ private final Map<Long, Position> positions = new ConcurrentHashMap<>();
+
+ public DeviceManager(DataManager dataManager) {
+ this.dataManager = dataManager;
+ this.config = Context.getConfig();
+ dataRefreshDelay = config.getLong("database.refreshDelay", DataManager.DEFAULT_REFRESH_DELAY) * 1000;
+ if (dataManager != null) {
+ try {
+ for (Position position : dataManager.getLatestPositions()) {
+ positions.put(position.getDeviceId(), position);
+ }
+ } catch (SQLException error) {
+ Log.warning(error);
+ }
+ }
+ }
+
+ private void updateDeviceCache(boolean force) throws SQLException {
+ boolean needWrite;
+ devicesLock.readLock().lock();
+ try {
+ needWrite = force || System.currentTimeMillis() - devicesLastUpdate > dataRefreshDelay;
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+
+ if (needWrite) {
+ devicesLock.writeLock().lock();
+ try {
+ if (force || System.currentTimeMillis() - devicesLastUpdate > dataRefreshDelay) {
+ devicesById.clear();
+ devicesByUniqueId.clear();
+ GeofenceManager geofenceManager = Context.getGeofenceManager();
+ for (Device device : dataManager.getAllDevices()) {
+ devicesById.put(device.getId(), device);
+ devicesByUniqueId.put(device.getUniqueId(), device);
+ if (geofenceManager != null) {
+ Position lastPosition = getLastPosition(device.getId());
+ if (lastPosition != null) {
+ device.setGeofenceIds(geofenceManager.getCurrentDeviceGeofences(lastPosition));
+ }
+ }
+ }
+ devicesLastUpdate = System.currentTimeMillis();
+ }
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+ }
+ }
+
+ @Override
+ public Device getDeviceById(long id) {
+ boolean forceUpdate;
+ devicesLock.readLock().lock();
+ try {
+ forceUpdate = !devicesById.containsKey(id);
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+
+ try {
+ updateDeviceCache(forceUpdate);
+ } catch (SQLException e) {
+ Log.warning(e);
+ }
+
+ devicesLock.readLock().lock();
+ try {
+ return devicesById.get(id);
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public Device getDeviceByUniqueId(String uniqueId) throws SQLException {
+ boolean forceUpdate;
+ devicesLock.readLock().lock();
+ try {
+ forceUpdate = !devicesByUniqueId.containsKey(uniqueId) && !config.getBoolean("database.ignoreUnknown");
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+
+ updateDeviceCache(forceUpdate);
+
+ devicesLock.readLock().lock();
+ try {
+ return devicesByUniqueId.get(uniqueId);
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+ }
+
+ public Collection<Device> getAllDevices() {
+ boolean forceUpdate;
+ devicesLock.readLock().lock();
+ try {
+ forceUpdate = devicesById.isEmpty();
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+
+ try {
+ updateDeviceCache(forceUpdate);
+ } catch (SQLException e) {
+ Log.warning(e);
+ }
+
+ devicesLock.readLock().lock();
+ try {
+ return devicesById.values();
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+ }
+
+ public Collection<Device> getDevices(long userId) throws SQLException {
+ Collection<Device> devices = new ArrayList<>();
+ devicesLock.readLock().lock();
+ try {
+ for (long id : Context.getPermissionsManager().getDevicePermissions(userId)) {
+ devices.add(devicesById.get(id));
+ }
+ } finally {
+ devicesLock.readLock().unlock();
+ }
+ return devices;
+ }
+
+ public void addDevice(Device device) throws SQLException {
+ dataManager.addDevice(device);
+
+ devicesLock.writeLock().lock();
+ try {
+ devicesById.put(device.getId(), device);
+ devicesByUniqueId.put(device.getUniqueId(), device);
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+ }
+
+ public void updateDevice(Device device) throws SQLException {
+ dataManager.updateDevice(device);
+
+ devicesLock.writeLock().lock();
+ try {
+ devicesById.put(device.getId(), device);
+ devicesByUniqueId.put(device.getUniqueId(), device);
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+ }
+
+ public void updateDeviceStatus(Device device) throws SQLException {
+ dataManager.updateDeviceStatus(device);
+
+ devicesLock.writeLock().lock();
+ try {
+ if (devicesById.containsKey(device.getId())) {
+ Device cachedDevice = devicesById.get(device.getId());
+ cachedDevice.setStatus(device.getStatus());
+ cachedDevice.setMotion(device.getMotion());
+ }
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+ }
+
+ public void removeDevice(long deviceId) throws SQLException {
+ dataManager.removeDevice(deviceId);
+
+ devicesLock.writeLock().lock();
+ try {
+ if (devicesById.containsKey(deviceId)) {
+ String deviceUniqueId = devicesById.get(deviceId).getUniqueId();
+ devicesById.remove(deviceId);
+ devicesByUniqueId.remove(deviceUniqueId);
+ }
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+
+ positions.remove(deviceId);
+ }
+
+ public void updateLatestPosition(Position position) throws SQLException {
+
+ Position lastPosition = getLastPosition(position.getDeviceId());
+ if (lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) > 0) {
+
+ dataManager.updateLatestPosition(position);
+
+ devicesLock.writeLock().lock();
+ try {
+ if (devicesById.containsKey(position.getDeviceId())) {
+ devicesById.get(position.getDeviceId()).setPositionId(position.getId());
+ }
+ } finally {
+ devicesLock.writeLock().unlock();
+ }
+
+ positions.put(position.getDeviceId(), position);
+
+ if (Context.getConnectionManager() != null) {
+ Context.getConnectionManager().updatePosition(position);
+ }
+ }
+ }
+
+ @Override
+ public Position getLastPosition(long deviceId) {
+ return positions.get(deviceId);
+ }
+
+ public Collection<Position> getInitialState(long userId) {
+
+ List<Position> result = new LinkedList<>();
+
+ if (Context.getPermissionsManager() != null) {
+ for (long deviceId : Context.getPermissionsManager().getDevicePermissions(userId)) {
+ if (positions.containsKey(deviceId)) {
+ result.add(positions.get(deviceId));
+ }
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/src/org/traccar/database/GeofenceManager.java b/src/org/traccar/database/GeofenceManager.java
index c35e19e9a..dc31172b9 100644
--- a/src/org/traccar/database/GeofenceManager.java
+++ b/src/org/traccar/database/GeofenceManager.java
@@ -173,7 +173,7 @@ public class GeofenceManager {
.add(deviceGeofence.getGeofenceId());
}
- for (Device device : dataManager.getAllDevicesCached()) {
+ for (Device device : Context.getDeviceManager().getAllDevices()) {
long groupId = device.getGroupId();
while (groupId != 0) {
getDeviceGeofences(deviceGeofencesWithGroups,
@@ -190,7 +190,7 @@ public class GeofenceManager {
} else {
deviceGeofenceIds.clear();
}
- Position lastPosition = Context.getConnectionManager().getLastPosition(device.getId());
+ Position lastPosition = Context.getIdentityManager().getLastPosition(device.getId());
if (lastPosition != null && deviceGeofencesWithGroups.containsKey(device.getId())) {
for (long geofenceId : deviceGeofencesWithGroups.get(device.getId())) {
Geofence geofence = getGeofence(geofenceId);
diff --git a/src/org/traccar/database/IdentityManager.java b/src/org/traccar/database/IdentityManager.java
index 8bdce09a3..8c0de8b38 100644
--- a/src/org/traccar/database/IdentityManager.java
+++ b/src/org/traccar/database/IdentityManager.java
@@ -16,6 +16,7 @@
package org.traccar.database;
import org.traccar.model.Device;
+import org.traccar.model.Position;
public interface IdentityManager {
@@ -23,4 +24,6 @@ public interface IdentityManager {
Device getDeviceByUniqueId(String uniqueId) throws Exception;
+ Position getLastPosition(long deviceId);
+
}
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index b6dd2e2a9..5a15375b4 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -78,7 +78,7 @@ public class PermissionsManager {
users.put(user.getId(), user);
}
- GroupTree groupTree = new GroupTree(dataManager.getAllGroups(), dataManager.getAllDevicesCached());
+ GroupTree groupTree = new GroupTree(dataManager.getAllGroups(), Context.getDeviceManager().getAllDevices());
for (GroupPermission permission : dataManager.getGroupPermissions()) {
Set<Long> userGroupPermissions = getGroupPermissions(permission.getUserId());
Set<Long> userDevicePermissions = getDevicePermissions(permission.getUserId());
diff --git a/src/org/traccar/events/GeofenceEventHandler.java b/src/org/traccar/events/GeofenceEventHandler.java
index 9a546182d..1ea7aee41 100644
--- a/src/org/traccar/events/GeofenceEventHandler.java
+++ b/src/org/traccar/events/GeofenceEventHandler.java
@@ -43,7 +43,7 @@ public class GeofenceEventHandler extends BaseEventHandler {
@Override
protected Collection<Event> analyzePosition(Position position) {
- Device device = dataManager.getDeviceById(position.getDeviceId());
+ Device device = Context.getIdentityManager().getDeviceById(position.getDeviceId());
if (device == null) {
return null;
}
diff --git a/src/org/traccar/events/MotionEventHandler.java b/src/org/traccar/events/MotionEventHandler.java
index d10513d26..4a3d2f0f0 100644
--- a/src/org/traccar/events/MotionEventHandler.java
+++ b/src/org/traccar/events/MotionEventHandler.java
@@ -38,7 +38,7 @@ public class MotionEventHandler extends BaseEventHandler {
@Override
protected Collection<Event> analyzePosition(Position position) {
- Device device = Context.getDataManager().getDeviceById(position.getDeviceId());
+ Device device = Context.getIdentityManager().getDeviceById(position.getDeviceId());
if (device == null) {
return null;
}
@@ -53,16 +53,19 @@ public class MotionEventHandler extends BaseEventHandler {
if (motion == null) {
motion = Device.STATUS_STOPPED;
}
- if (valid && speed > SPEED_THRESHOLD && !motion.equals(Device.STATUS_MOVING)) {
- Context.getConnectionManager().updateDevice(position.getDeviceId(), Device.STATUS_MOVING, null);
- result = new ArrayList<>();
- result.add(new Event(Event.TYPE_DEVICE_MOVING, position.getDeviceId(), position.getId()));
- } else if (valid && speed < SPEED_THRESHOLD && motion.equals(Device.STATUS_MOVING)) {
- Context.getConnectionManager().updateDevice(position.getDeviceId(), Device.STATUS_STOPPED, null);
- result = new ArrayList<>();
- result.add(new Event(Event.TYPE_DEVICE_STOPPED, position.getDeviceId(), position.getId()));
- }
try {
+ if (valid && speed > SPEED_THRESHOLD && !motion.equals(Device.STATUS_MOVING)) {
+ device.setMotion(Device.STATUS_MOVING);
+ Context.getDeviceManager().updateDeviceStatus(device);
+ result = new ArrayList<>();
+ result.add(new Event(Event.TYPE_DEVICE_MOVING, position.getDeviceId(), position.getId()));
+ } else if (valid && speed < SPEED_THRESHOLD && motion.equals(Device.STATUS_MOVING)) {
+ device.setMotion(Device.STATUS_STOPPED);
+ Context.getDeviceManager().updateDeviceStatus(device);
+ result = new ArrayList<>();
+ result.add(new Event(Event.TYPE_DEVICE_STOPPED, position.getDeviceId(), position.getId()));
+ }
+
if (result != null && !result.isEmpty()) {
for (Event event : result) {
if (!Context.getDataManager().getLastEvents(position.getDeviceId(),
diff --git a/src/org/traccar/events/OverspeedEventHandler.java b/src/org/traccar/events/OverspeedEventHandler.java
index e14d4bcea..fd005e170 100644
--- a/src/org/traccar/events/OverspeedEventHandler.java
+++ b/src/org/traccar/events/OverspeedEventHandler.java
@@ -40,7 +40,7 @@ public class OverspeedEventHandler extends BaseEventHandler {
@Override
protected Collection<Event> analyzePosition(Position position) {
- Device device = Context.getDataManager().getDeviceById(position.getDeviceId());
+ Device device = Context.getIdentityManager().getDeviceById(position.getDeviceId());
if (device == null) {
return null;
}
diff --git a/test/org/traccar/ProtocolTest.java b/test/org/traccar/ProtocolTest.java
index 503bc4c00..07a19b691 100644
--- a/test/org/traccar/ProtocolTest.java
+++ b/test/org/traccar/ProtocolTest.java
@@ -44,6 +44,11 @@ public class ProtocolTest {
public Device getDeviceByUniqueId(String uniqueId) {
return createDevice();
}
+
+ @Override
+ public Position getLastPosition(long deviceId) {
+ return null;
+ }
});
}