[Minor] Optimizations, reduce memory and calls in Transaction and ObjectFilter

This commit is contained in:
Robert von Burg 2019-09-25 11:13:45 +02:00
parent edf60923ac
commit aec29adcd1
7 changed files with 156 additions and 57 deletions

View File

@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -15,6 +15,7 @@
*/
package li.strolch.agent.impl;
import java.util.HashSet;
import java.util.List;
import li.strolch.agent.api.ActivityMap;
@ -29,9 +30,8 @@ import li.strolch.utils.dbc.DBC;
/**
* This is the {@link AuditTrail} for {@link Activity Activities}
*
*
* @author Robert von Burg <eitch@eitchnet.ch>
*
* @see AuditingElementMapFacade
*/
public class AuditingActivityMap extends AuditingElementMapFacade<Activity> implements ActivityMap {
@ -55,6 +55,8 @@ public class AuditingActivityMap extends AuditingElementMapFacade<Activity> impl
ActivityVisitor<U> activityVisitor = query.getVisitor();
DBC.PRE.assertNotNull("activityVisitor on query", activityVisitor);
query.setVisitor(activity -> {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(activity);
return activity.accept(activityVisitor);
});

View File

@ -15,11 +15,10 @@
*/
package li.strolch.agent.impl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import java.util.*;
import java.util.stream.Stream;
import li.strolch.agent.api.AuditTrail;
@ -65,12 +64,6 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
DBC.PRE.assertNotNull("ElementMap must be set!", elementMap); //$NON-NLS-1$
this.elementMap = elementMap;
this.observeAccessReads = observeAccessReads;
this.created = new HashSet<>();
this.read = new HashSet<>();
this.updated = new HashSet<>();
this.deleted = new HashSet<>();
this.deletedAllByType = new HashMap<>();
}
protected ElementMap<T> getElementMap() {
@ -81,6 +74,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
* @return the read
*/
public Set<T> getRead() {
if (this.read == null)
return emptySet();
return this.read;
}
@ -88,6 +83,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
* @return the created
*/
public Set<T> getCreated() {
if (this.created == null)
return emptySet();
return this.created;
}
@ -95,6 +92,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
* @return the updated
*/
public Set<T> getUpdated() {
if (this.updated == null)
return emptySet();
return this.updated;
}
@ -102,6 +101,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
* @return the deleted
*/
public Set<T> getDeleted() {
if (this.deleted == null)
return emptySet();
return this.deleted;
}
@ -116,6 +117,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
* @return the deletedAllByType
*/
public Map<String, Long> getDeletedAllByType() {
if (this.deletedAllByType == null)
return emptyMap();
return this.deletedAllByType;
}
@ -142,24 +145,33 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public T getTemplate(StrolchTransaction tx, String type) {
T template = this.elementMap.getTemplate(tx, type);
if (this.observeAccessReads && template != null)
if (this.observeAccessReads && template != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(template);
}
return template;
}
@Override
public T getTemplate(StrolchTransaction tx, String type, boolean assertExists) throws StrolchException {
T template = this.elementMap.getTemplate(tx, type, assertExists);
if (this.observeAccessReads && template != null)
if (this.observeAccessReads && template != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(template);
}
return template;
}
@Override
public T getBy(StrolchTransaction tx, String type, String id) {
T element = this.elementMap.getBy(tx, type, id);
if (this.observeAccessReads && element != null)
if (this.observeAccessReads && element != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(element);
}
return element;
}
@ -168,16 +180,22 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public T getBy(StrolchTransaction tx, String type, String id, boolean assertExists) throws StrolchException {
T element = this.elementMap.getBy(tx, type, id, assertExists);
if (this.observeAccessReads && element != null)
if (this.observeAccessReads && element != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(element);
}
return element;
}
@Override
public T getBy(StrolchTransaction tx, String type, String id, int version) {
T element = this.elementMap.getBy(tx, type, id, version);
if (this.observeAccessReads && element != null)
if (this.observeAccessReads && element != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(element);
}
return element;
}
@ -185,16 +203,22 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
public T getBy(StrolchTransaction tx, String type, String id, int version, boolean assertExists)
throws StrolchException {
T element = this.elementMap.getBy(tx, type, id, version, assertExists);
if (this.observeAccessReads && element != null)
if (this.observeAccessReads && element != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(element);
}
return element;
}
@Override
public T getBy(StrolchTransaction tx, StringParameter refP, boolean assertExists) throws StrolchException {
T element = this.elementMap.getBy(tx, refP, assertExists);
if (this.observeAccessReads && element != null)
if (this.observeAccessReads && element != null) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(element);
}
return element;
}
@ -202,16 +226,22 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
public List<T> getBy(StrolchTransaction tx, StringListParameter refP, boolean assertExists)
throws StrolchException {
List<T> elements = this.elementMap.getBy(tx, refP, assertExists);
if (this.observeAccessReads && !elements.isEmpty())
if (this.observeAccessReads && !elements.isEmpty()) {
if (this.read == null)
this.read = new HashSet<>();
this.read.addAll(elements);
}
return elements;
}
@Override
public List<T> getVersionsFor(StrolchTransaction tx, String type, String id) {
List<T> versions = this.elementMap.getVersionsFor(tx, type, id);
if (this.observeAccessReads && !versions.isEmpty())
if (this.observeAccessReads && !versions.isEmpty()) {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(versions.get(versions.size() - 1));
}
return versions;
}
@ -223,24 +253,33 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public List<T> getAllElements(StrolchTransaction tx) {
List<T> elements = this.elementMap.getAllElements(tx);
if (this.observeAccessReads && !elements.isEmpty())
if (this.observeAccessReads && !elements.isEmpty()) {
if (this.read == null)
this.read = new HashSet<>();
this.read.addAll(elements);
}
return elements;
}
@Override
public List<T> getElementsBy(StrolchTransaction tx, String type) {
List<T> elements = this.elementMap.getElementsBy(tx, type);
if (this.observeAccessReads && !elements.isEmpty())
if (this.observeAccessReads && !elements.isEmpty()) {
if (this.read == null)
this.read = new HashSet<>();
this.read.addAll(elements);
}
return elements;
}
@Override
public Stream<T> stream(StrolchTransaction tx, String... types) {
Stream<T> stream = this.elementMap.stream(tx, types);
if (this.observeAccessReads)
if (this.observeAccessReads) {
if (this.read == null)
this.read = new HashSet<>();
stream = stream.peek(e -> this.read.add(e));
}
return stream;
}
@ -262,36 +301,48 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public void add(StrolchTransaction tx, T element) {
this.elementMap.add(tx, element);
if (this.created == null)
this.created = new HashSet<>();
this.created.add(element);
}
@Override
public void addAll(StrolchTransaction tx, List<T> elements) {
this.elementMap.addAll(tx, elements);
if (this.created == null)
this.created = new HashSet<>();
this.created.addAll(elements);
}
@Override
public void update(StrolchTransaction tx, T element) {
this.elementMap.update(tx, element);
if (this.updated == null)
this.updated = new HashSet<>();
this.updated.add(element);
}
@Override
public void updateAll(StrolchTransaction tx, List<T> elements) {
this.elementMap.updateAll(tx, elements);
if (this.updated == null)
this.updated = new HashSet<>();
this.updated.addAll(elements);
}
@Override
public void remove(StrolchTransaction tx, T element) {
this.elementMap.remove(tx, element);
if (this.deleted == null)
this.deleted = new HashSet<>();
this.deleted.add(element);
}
@Override
public void removeAll(StrolchTransaction tx, List<T> elements) {
this.elementMap.removeAll(tx, elements);
if (this.deleted == null)
this.deleted = new HashSet<>();
this.deleted.addAll(elements);
}
@ -306,6 +357,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
public long removeAllBy(StrolchTransaction tx, String type) {
long removed = this.elementMap.removeAllBy(tx, type);
if (this.deletedAllByType == null)
this.deletedAllByType = new HashMap<>();
Long byType = this.deletedAllByType.get(type);
if (byType == null)
byType = 0L;
@ -318,6 +371,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public T revertToVersion(StrolchTransaction tx, String type, String id, int version) throws StrolchException {
T element = this.elementMap.revertToVersion(tx, type, id, version);
if (this.updated == null)
this.updated = new HashSet<>();
this.updated.add(element);
return element;
}
@ -325,6 +380,8 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public T revertToVersion(StrolchTransaction tx, T element) throws StrolchException {
T revertedElement = this.elementMap.revertToVersion(tx, element);
if (this.updated == null)
this.updated = new HashSet<>();
this.updated.add(revertedElement);
return revertedElement;
}
@ -332,9 +389,14 @@ public abstract class AuditingElementMapFacade<T extends StrolchRootElement> imp
@Override
public void undoVersion(StrolchTransaction tx, T element) throws StrolchException {
this.elementMap.undoVersion(tx, element);
if (element.getVersion().isFirstVersion())
if (element.getVersion().isFirstVersion()) {
if (this.deleted == null)
this.deleted = new HashSet<>();
this.deleted.add(element);
else
} else {
if (this.updated == null)
this.updated = new HashSet<>();
this.updated.add(element);
}
}
}

View File

@ -15,6 +15,7 @@
*/
package li.strolch.agent.impl;
import java.util.HashSet;
import java.util.List;
import li.strolch.agent.api.AuditTrail;
@ -55,6 +56,8 @@ public class AuditingOrderMap extends AuditingElementMapFacade<Order> implements
OrderVisitor<U> orderVisitor = query.getVisitor();
DBC.PRE.assertNotNull("orderVisitor on query", orderVisitor);
query.setVisitor(order -> {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(order);
return order.accept(orderVisitor);
});

View File

@ -1,12 +1,12 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -15,6 +15,7 @@
*/
package li.strolch.agent.impl;
import java.util.HashSet;
import java.util.List;
import li.strolch.agent.api.AuditTrail;
@ -29,9 +30,8 @@ import li.strolch.utils.dbc.DBC;
/**
* This is the {@link AuditTrail} for {@link Resource Resources}
*
*
* @author Robert von Burg <eitch@eitchnet.ch>
*
* @see AuditingElementMapFacade
*/
public class AuditingResourceMap extends AuditingElementMapFacade<Resource> implements ResourceMap {
@ -55,6 +55,8 @@ public class AuditingResourceMap extends AuditingElementMapFacade<Resource> impl
ResourceVisitor<U> resourceVisitor = query.getVisitor();
DBC.PRE.assertNotNull("resourceVisitor on query", resourceVisitor);
query.setVisitor(resource -> {
if (this.read == null)
this.read = new HashSet<>();
this.read.add(resource);
return resource.accept(resourceVisitor);
});

View File

@ -1510,34 +1510,45 @@ public abstract class AbstractTransaction implements StrolchTransaction {
ObserverEvent event = new ObserverEvent();
if (this.resourceMap != null) {
if (!this.resourceMap.getCreated().isEmpty())
event.added.addList(Tags.RESOURCE, new ArrayList<>(this.resourceMap.getCreated()));
if (!this.resourceMap.getUpdated().isEmpty())
event.updated.addList(Tags.RESOURCE, new ArrayList<>(this.resourceMap.getUpdated()));
if (!this.resourceMap.getDeleted().isEmpty())
event.removed.addList(Tags.RESOURCE, new ArrayList<>(this.resourceMap.getDeleted()));
Set<Resource> created = this.resourceMap.getCreated();
if (!created.isEmpty())
event.added.addList(Tags.RESOURCE, new ArrayList<>(created));
Set<Resource> updated = this.resourceMap.getUpdated();
if (!updated.isEmpty())
event.updated.addList(Tags.RESOURCE, new ArrayList<>(updated));
Set<Resource> deleted = this.resourceMap.getDeleted();
if (!deleted.isEmpty())
event.removed.addList(Tags.RESOURCE, new ArrayList<>(deleted));
}
if (this.orderMap != null) {
if (!this.orderMap.getCreated().isEmpty())
event.added.addList(Tags.ORDER, new ArrayList<>(this.orderMap.getCreated()));
if (!this.orderMap.getUpdated().isEmpty())
event.updated.addList(Tags.ORDER, new ArrayList<>(this.orderMap.getUpdated()));
if (!this.orderMap.getDeleted().isEmpty())
event.removed.addList(Tags.ORDER, new ArrayList<>(this.orderMap.getDeleted()));
Set<Order> created = this.orderMap.getCreated();
if (!created.isEmpty())
event.added.addList(Tags.ORDER, new ArrayList<>(created));
Set<Order> updated = this.orderMap.getUpdated();
if (!updated.isEmpty())
event.updated.addList(Tags.ORDER, new ArrayList<>(updated));
Set<Order> deleted = this.orderMap.getDeleted();
if (!deleted.isEmpty())
event.removed.addList(Tags.ORDER, new ArrayList<>(deleted));
}
if (this.activityMap != null) {
if (!this.activityMap.getCreated().isEmpty())
event.added.addList(Tags.ACTIVITY, new ArrayList<>(this.activityMap.getCreated()));
if (!this.activityMap.getUpdated().isEmpty())
event.updated.addList(Tags.ACTIVITY, new ArrayList<>(this.activityMap.getUpdated()));
if (!this.activityMap.getDeleted().isEmpty())
event.removed.addList(Tags.ACTIVITY, new ArrayList<>(this.activityMap.getDeleted()));
Set<Activity> created = this.activityMap.getCreated();
if (!created.isEmpty())
event.added.addList(Tags.ACTIVITY, new ArrayList<>(created));
Set<Activity> updated = this.activityMap.getUpdated();
if (!updated.isEmpty())
event.updated.addList(Tags.ACTIVITY, new ArrayList<>(updated));
Set<Activity> deleted = this.activityMap.getDeleted();
if (!deleted.isEmpty())
event.removed.addList(Tags.ACTIVITY, new ArrayList<>(deleted));
}
ObserverHandler observerHandler = this.realm.getObserverHandler();
observerHandler.notify(event);
if (!(event.added.isEmpty() && event.updated.isEmpty() && event.removed.isEmpty())) {
ObserverHandler observerHandler = this.realm.getObserverHandler();
observerHandler.notify(event);
}
return System.nanoTime() - observerUpdateStart;
}

View File

@ -6,6 +6,7 @@
<Properties>
<locale>en</locale>
<verbose>true</verbose>
<timezone>Europe/Zurich</timezone>
</Properties>
</Runtime>
<Component>

View File

@ -89,8 +89,8 @@ public class ObjectFilter {
* Default constructor initializing the filter
*/
public ObjectFilter() {
this.cache = new MapOfMaps<>(1);
this.keySet = new HashSet<>(1);
this.cache = new MapOfMaps<>();
this.keySet = new HashSet<>();
}
private void replaceKey(ObjectCache cached, Object newObjectKey, Object newObject) {
@ -455,6 +455,8 @@ public class ObjectFilter {
* @return The list of all objects registered under the given key and that need to be added.
*/
public List<Object> getAdded(String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<Object> addedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -476,6 +478,8 @@ public class ObjectFilter {
* @return The list of all objects registered under the given key and that need to be added.
*/
public <V> List<V> getAdded(Class<V> clazz, String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<V> addedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -499,6 +503,8 @@ public class ObjectFilter {
* @return The list of all objects registered under the given key and that need to be updated.
*/
public List<Object> getUpdated(String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<Object> updatedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -520,6 +526,8 @@ public class ObjectFilter {
* @return The list of all objects registered under the given key and that need to be updated.
*/
public <V> List<V> getUpdated(Class<V> clazz, String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<V> updatedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -543,6 +551,8 @@ public class ObjectFilter {
* @return The list of object registered under the given key that have, as a final action, removal.
*/
public List<Object> getRemoved(String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<Object> removedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -564,6 +574,8 @@ public class ObjectFilter {
* @return The list of object registered under the given key that have, as a final action, removal.
*/
public <V> List<V> getRemoved(Class<V> clazz, String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<V> removedObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -589,6 +601,8 @@ public class ObjectFilter {
* @return The list of object registered under the given key that have, as a final action, removal.
*/
public <V> List<V> getAll(Class<V> clazz, String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<V> objects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -632,6 +646,8 @@ public class ObjectFilter {
* @return The list of objects matching the given key.
*/
public List<Object> getAll(String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
List<Object> allObjects = new LinkedList<>();
List<ObjectCache> allObjs = this.cache.getAllElements(key);
for (ObjectCache objectCache : allObjs) {
@ -650,6 +666,8 @@ public class ObjectFilter {
* @return The list of objects matching the given key.
*/
public List<ObjectCache> getCache(String key) {
if (!this.cache.containsMap(key))
return Collections.emptyList();
return this.cache.getAllElements(key);
}