From cd229daa23cfc43ad5056c45c4aaecefdbbf826c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 8 Jun 2022 07:52:59 -0700 Subject: Improve cache invalidation --- .../java/org/traccar/api/BaseObjectResource.java | 8 ++++ .../traccar/api/resource/PermissionsResource.java | 9 ++++ .../handler/events/MaintenanceEventHandler.java | 3 +- .../org/traccar/session/cache/CacheManager.java | 50 ++++++++++++---------- .../java/org/traccar/session/cache/CacheValue.java | 6 ++- 5 files changed, 52 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/main/java/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java index d6401dc42..c033fbb62 100644 --- a/src/main/java/org/traccar/api/BaseObjectResource.java +++ b/src/main/java/org/traccar/api/BaseObjectResource.java @@ -27,11 +27,13 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.model.Permission; import org.traccar.model.User; +import org.traccar.session.cache.CacheManager; import org.traccar.storage.StorageException; import org.traccar.storage.query.Columns; import org.traccar.storage.query.Condition; import org.traccar.storage.query.Request; +import javax.inject.Inject; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -42,6 +44,9 @@ import javax.ws.rs.core.Response; public abstract class BaseObjectResource extends BaseResource { + @Inject + private CacheManager cacheManager; + protected final Class baseClass; public BaseObjectResource(Class baseClass) { @@ -75,6 +80,7 @@ public abstract class BaseObjectResource extends BaseResour LogAction.create(getUserId(), entity); storage.addPermission(new Permission(User.class, getUserId(), baseClass, entity.getId())); + cacheManager.invalidate(User.class, getUserId(), baseClass, entity.getId()); LogAction.link(getUserId(), User.class, getUserId(), baseClass, entity.getId()); if (manager instanceof SimpleObjectManager) { @@ -100,6 +106,7 @@ public abstract class BaseObjectResource extends BaseResour new Columns.Exclude("id"), new Condition.Equals("id", "id"))); } + cacheManager.updateOrInvalidate(baseClass, entity.getId()); LogAction.edit(getUserId(), entity); @@ -128,6 +135,7 @@ public abstract class BaseObjectResource extends BaseResour } else { storage.removeObject(baseClass, new Request(new Condition.Equals("id", "id", id))); } + cacheManager.updateOrInvalidate(baseClass, id); LogAction.remove(getUserId(), baseClass, id); diff --git a/src/main/java/org/traccar/api/resource/PermissionsResource.java b/src/main/java/org/traccar/api/resource/PermissionsResource.java index 484c61e66..a4db6754c 100644 --- a/src/main/java/org/traccar/api/resource/PermissionsResource.java +++ b/src/main/java/org/traccar/api/resource/PermissionsResource.java @@ -20,8 +20,10 @@ import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.helper.LogAction; import org.traccar.model.Permission; +import org.traccar.session.cache.CacheManager; import org.traccar.storage.StorageException; +import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.POST; @@ -40,6 +42,9 @@ import java.util.Set; @Consumes(MediaType.APPLICATION_JSON) public class PermissionsResource extends BaseResource { + @Inject + private CacheManager cacheManager; + private void checkPermission(Permission permission, boolean link) throws StorageException { if (permissionsService.notAdmin(getUserId())) { permissionsService.checkPermission(permission.getOwnerClass(), getUserId(), permission.getOwnerId()); @@ -67,6 +72,8 @@ public class PermissionsResource extends BaseResource { checkPermission(permission, true); Context.getDataManager().linkObject(permission.getOwnerClass(), permission.getOwnerId(), permission.getPropertyClass(), permission.getPropertyId(), true); + cacheManager.invalidate(permission.getOwnerClass(), permission.getOwnerId(), + permission.getPropertyClass(), permission.getPropertyId()); LogAction.link(getUserId(), permission.getOwnerClass(), permission.getOwnerId(), permission.getPropertyClass(), permission.getPropertyId()); } @@ -91,6 +98,8 @@ public class PermissionsResource extends BaseResource { checkPermission(permission, false); Context.getDataManager().linkObject(permission.getOwnerClass(), permission.getOwnerId(), permission.getPropertyClass(), permission.getPropertyId(), false); + cacheManager.invalidate(permission.getOwnerClass(), permission.getOwnerId(), + permission.getPropertyClass(), permission.getPropertyId()); LogAction.unlink(getUserId(), permission.getOwnerClass(), permission.getOwnerId(), permission.getPropertyClass(), permission.getPropertyId()); } diff --git a/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java index be3e9bf8d..f85aab043 100644 --- a/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java +++ b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.Map; import io.netty.channel.ChannelHandler; +import org.traccar.Context; import org.traccar.model.Event; import org.traccar.model.Maintenance; import org.traccar.model.Position; @@ -39,7 +40,7 @@ public class MaintenanceEventHandler extends BaseEventHandler { @Override protected Map analyzePosition(Position position) { - Position lastPosition = cacheManager.getPosition(position.getDeviceId()); + Position lastPosition = Context.getIdentityManager().getLastPosition(position.getDeviceId()); if (lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) < 0) { return null; } diff --git a/src/main/java/org/traccar/session/cache/CacheManager.java b/src/main/java/org/traccar/session/cache/CacheManager.java index 586237655..8e1737441 100644 --- a/src/main/java/org/traccar/session/cache/CacheManager.java +++ b/src/main/java/org/traccar/session/cache/CacheManager.java @@ -20,9 +20,9 @@ import org.traccar.model.BaseModel; import org.traccar.model.Device; import org.traccar.model.Driver; import org.traccar.model.Geofence; +import org.traccar.model.GroupedModel; import org.traccar.model.Maintenance; import org.traccar.model.Notification; -import org.traccar.model.Position; import org.traccar.model.Server; import org.traccar.model.User; import org.traccar.storage.Storage; @@ -59,7 +59,6 @@ public class CacheManager { private final Map, List>> deviceLinks = new HashMap<>(); private Server server; - private final Map devicePositions = new HashMap<>(); private final Map> notificationUsers = new HashMap<>(); @Inject @@ -90,15 +89,6 @@ public class CacheManager { } } - public Position getPosition(long deviceId) { - try { - lock.readLock().lock(); - return devicePositions.get(deviceId); - } finally { - lock.readLock().unlock(); - } - } - public Server getServer() { try { lock.readLock().lock(); @@ -146,18 +136,34 @@ public class CacheManager { } } - public void updatePosition(Position position) { - try { - lock.writeLock().lock(); - devicePositions.put(position.getDeviceId(), position); - } finally { - lock.writeLock().unlock(); + public void updateOrInvalidate(Class clazz, long id) throws StorageException { + boolean invalidate = false; + var before = getObject(clazz, id); + var after = storage.getObject(clazz, new Request( + new Columns.All(), new Condition.Equals("id", "id", id))); + if (before == null) { + return; + } else if (after == null) { + invalidate = true; + } else if (clazz.isInstance(GroupedModel.class)) { + if (((GroupedModel) before).getGroupId() != ((GroupedModel) after).getGroupId()) { + invalidate = true; + } + } + if (invalidate) { + invalidate(new CacheKey(clazz, id)); + } else { + try { + lock.writeLock().lock(); + var cacheValue = deviceCache.get(new CacheKey(clazz, id)); + if (cacheValue != null) { + cacheValue.setValue(after); + } + // TODO if device, also need to update geofences + } finally { + lock.writeLock().unlock(); + } } - } - - public void invalidate( - Class clazz, long id) throws StorageException { - invalidate(new CacheKey(clazz, id)); } public void invalidate( diff --git a/src/main/java/org/traccar/session/cache/CacheValue.java b/src/main/java/org/traccar/session/cache/CacheValue.java index 9e955dfe5..1f0383ce5 100644 --- a/src/main/java/org/traccar/session/cache/CacheValue.java +++ b/src/main/java/org/traccar/session/cache/CacheValue.java @@ -22,7 +22,7 @@ import java.util.Set; class CacheValue { - private final BaseModel value; + private BaseModel value; private final Set references = new HashSet<>(); CacheValue(BaseModel value) { @@ -42,6 +42,10 @@ class CacheValue { return (T) value; } + public void setValue(BaseModel value) { + this.value = value; + } + public Set getReferences() { return references; } -- cgit v1.2.3