This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push:
new 2ff64413d Revert "CAY-2876 Memory leak in the ObjectStore"
2ff64413d is described below
commit 2ff64413d4a7c7d1f98ac59f74770e166545ed21
Author: Nikita Timofeev <[email protected]>
AuthorDate: Mon Mar 10 16:13:34 2025 +0400
Revert "CAY-2876 Memory leak in the ObjectStore"
This reverts commit bf344662776351b64deb1fdf0bbe0676db86c92e.
---
RELEASE-NOTES.txt | 1 -
.../commitlog/CommitLogFilter_All_FlattenedIT.java | 10 +-
.../access/DefaultObjectMapRetainStrategy.java | 4 +-
.../apache/cayenne/access/NoSyncObjectStore.java | 4 +-
.../java/org/apache/cayenne/access/ObjectDiff.java | 43 ++---
.../cayenne/access/ObjectMapRetainStrategy.java | 4 +-
.../org/apache/cayenne/access/ObjectStore.java | 195 ++++++++++-----------
.../apache/cayenne/access/ObjectStoreEntry.java | 70 --------
.../cayenne/access/ObjectStoreGraphDiff.java | 7 +-
.../access/DataContextPrefetchMultistepIT.java | 2 +-
.../cayenne/access/DataContextSerializationIT.java | 4 +-
.../org/apache/cayenne/access/ObjectStoreTest.java | 2 +-
12 files changed, 127 insertions(+), 219 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 52ab66e33..f964462b3 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -21,7 +21,6 @@ Bug Fixes:
CAY-2701 MySQL DST-related LocalDateTime issues
CAY-2871 QualifierTranslator breaks on a relationship with a compound FK
CAY-2872 CayenneModeler "Documentation" link is broken
-CAY-2876 Memory leak in the ObjectStore
CAY-2879 Negative number for non parameterized ObjectSelect query not
processed correctly
----------------------------------
diff --git
a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_All_FlattenedIT.java
b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_All_FlattenedIT.java
index 63c0f1a6e..7a755890a 100644
---
a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_All_FlattenedIT.java
+++
b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilter_All_FlattenedIT.java
@@ -27,8 +27,6 @@ import org.apache.cayenne.commitlog.model.ObjectChange;
import org.apache.cayenne.commitlog.model.ObjectChangeType;
import org.apache.cayenne.commitlog.model.ToManyRelationshipChange;
import org.apache.cayenne.commitlog.unit.FlattenedRuntimeCase;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.runtime.CoreModule;
import org.apache.cayenne.query.SelectById;
import org.apache.cayenne.runtime.CayenneRuntimeBuilder;
import org.junit.Before;
@@ -50,8 +48,6 @@ public class CommitLogFilter_All_FlattenedIT extends
FlattenedRuntimeCase {
protected CayenneRuntimeBuilder configureCayenne() {
this.mockListener = mock(CommitLogListener.class);
return super.configureCayenne()
- .addModule(b -> CoreModule.extend(b)
-
.setProperty(Constants.OBJECT_RETAIN_STRATEGY_PROPERTY, "soft"))
.addModule(b ->
CommitLogModule.extend(b).addListener(mockListener));
}
@@ -67,9 +63,9 @@ public class CommitLogFilter_All_FlattenedIT extends
FlattenedRuntimeCase {
e4.insert(12);
e34.insert(1, 11);
- E3 e3 = SelectById.queryId(E3.class, 1).selectOne(context);
- E4 e4_1 = SelectById.queryId(E4.class, 11).selectOne(context);
- E4 e4_2 = SelectById.queryId(E4.class, 12).selectOne(context);
+ E3 e3 = SelectById.query(E3.class, 1).selectOne(context);
+ E4 e4_1 = SelectById.query(E4.class, 11).selectOne(context);
+ E4 e4_2 = SelectById.query(E4.class, 12).selectOne(context);
doAnswer((Answer<Object>) invocation -> {
diff --git
a/cayenne/src/main/java/org/apache/cayenne/access/DefaultObjectMapRetainStrategy.java
b/cayenne/src/main/java/org/apache/cayenne/access/DefaultObjectMapRetainStrategy.java
index 8fcbf42db..05f248ed8 100644
---
a/cayenne/src/main/java/org/apache/cayenne/access/DefaultObjectMapRetainStrategy.java
+++
b/cayenne/src/main/java/org/apache/cayenne/access/DefaultObjectMapRetainStrategy.java
@@ -22,7 +22,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.di.Inject;
@@ -46,7 +46,7 @@ public class DefaultObjectMapRetainStrategy implements
ObjectMapRetainStrategy {
this.runtimeProperties = runtimeProperties;
}
- public Map<ObjectId, ObjectStoreEntry> createObjectMap() {
+ public Map<Object, Persistent> createObjectMap() {
String strategy =
runtimeProperties.get(Constants.OBJECT_RETAIN_STRATEGY_PROPERTY);
if (strategy == null || WEAK_RETAIN_STRATEGY.equals(strategy)) {
diff --git
a/cayenne/src/main/java/org/apache/cayenne/access/NoSyncObjectStore.java
b/cayenne/src/main/java/org/apache/cayenne/access/NoSyncObjectStore.java
index 914543a23..9358c08d2 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/NoSyncObjectStore.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/NoSyncObjectStore.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.access;
import java.util.Map;
-import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
/**
* An {@link ObjectStore} which doesn't receive notifications
@@ -30,7 +30,7 @@ import org.apache.cayenne.ObjectId;
*/
public class NoSyncObjectStore extends ObjectStore {
- public NoSyncObjectStore(DataRowStore dataRowCache, Map<ObjectId,
ObjectStoreEntry> objectMap) {
+ public NoSyncObjectStore(DataRowStore dataRowCache, Map<Object,
Persistent> objectMap) {
super(dataRowCache, objectMap);
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ObjectDiff.java
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectDiff.java
index 6ae2df6d3..9b2b68de4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectDiff.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectDiff.java
@@ -65,22 +65,23 @@ public class ObjectDiff extends NodeDiff {
private Map<ArcOperation, ArcOperation> flatIds;
private Map<ArcOperation, ArcOperation> phantomFks;
- private final ObjectStoreEntry entry;
+ private Persistent object;
- ObjectDiff(final ObjectStoreEntry entry) {
+ ObjectDiff(final Persistent object) {
- super(entry.persistent().getObjectId());
+ super(object.getObjectId());
- // retain the object, as ObjectStore may have weak references to
registered objects,
- // and we can't allow it to deallocate dirty objects.
- this.entry = entry;
+ // retain the object, as ObjectStore may have weak references to
+ // registered
+ // objects and we can't allow it to deallocate dirty objects.
+ this.object = object;
- EntityResolver entityResolver =
object().getObjectContext().getEntityResolver();
+ EntityResolver entityResolver =
object.getObjectContext().getEntityResolver();
- this.entityName = object().getObjectId().getEntityName();
+ this.entityName = object.getObjectId().getEntityName();
this.classDescriptor = entityResolver.getClassDescriptor(entityName);
- int state = object().getPersistenceState();
+ int state = object.getPersistenceState();
// take snapshot of simple properties and arcs used for optimistic
// locking..
@@ -98,7 +99,7 @@ public class ObjectDiff extends NodeDiff {
@Override
public boolean visitAttribute(AttributeProperty property) {
- snapshot.put(property.getName(),
property.readProperty(object()));
+ snapshot.put(property.getName(),
property.readProperty(object));
return true;
}
@@ -113,8 +114,8 @@ public class ObjectDiff extends NodeDiff {
// eagerly resolve optimistically locked relationships
Object target = (lock && isUsedForLocking)
- ? property.readProperty(object())
- : property.readPropertyDirectly(object());
+ ? property.readProperty(object)
+ : property.readPropertyDirectly(object);
if (target instanceof Persistent) {
target = ((Persistent) target).getObjectId();
@@ -128,15 +129,15 @@ public class ObjectDiff extends NodeDiff {
}
}
- Persistent object() {
- return entry.persistent();
+ Object getObject() {
+ return object;
}
ClassDescriptor getClassDescriptor() {
// class descriptor is initiated in constructor, but is nullified on
// serialization
if (classDescriptor == null) {
- EntityResolver entityResolver =
object().getObjectContext().getEntityResolver();
+ EntityResolver entityResolver =
object.getObjectContext().getEntityResolver();
this.classDescriptor =
entityResolver.getClassDescriptor(entityName);
}
@@ -151,7 +152,7 @@ public class ObjectDiff extends NodeDiff {
Object value = arcSnapshot != null ? arcSnapshot.get(propertyName) :
null;
if (value instanceof Fault) {
- Persistent target = (Persistent) ((Fault)
value).resolveFault(object(), propertyName);
+ Persistent target = (Persistent) ((Fault)
value).resolveFault(object, propertyName);
value = target != null ? target.getObjectId() : null;
arcSnapshot.put(propertyName, value);
@@ -166,7 +167,7 @@ public class ObjectDiff extends NodeDiff {
public ObjectId getCurrentArcSnapshotValue(String propertyName) {
Object value = currentArcSnapshot != null ?
currentArcSnapshot.get(propertyName) : null;
if (value instanceof Fault) {
- Persistent target = (Persistent) ((Fault)
value).resolveFault(object(), propertyName);
+ Persistent target = (Persistent) ((Fault)
value).resolveFault(object, propertyName);
value = target != null ? target.getObjectId() : null;
currentArcSnapshot.put(propertyName, value);
@@ -327,7 +328,7 @@ public class ObjectDiff extends NodeDiff {
return false;
}
- int state = object().getPersistenceState();
+ int state = object.getPersistenceState();
if (state == PersistenceState.NEW || state ==
PersistenceState.DELETED) {
return false;
}
@@ -341,7 +342,7 @@ public class ObjectDiff extends NodeDiff {
public boolean visitAttribute(AttributeProperty property) {
Object oldValue = snapshot.get(property.getName());
- Object newValue = property.readProperty(object());
+ Object newValue = property.readProperty(object);
if (!property.equals(oldValue, newValue)) {
modFound[0] = true;
@@ -362,7 +363,7 @@ public class ObjectDiff extends NodeDiff {
return true;
}
- Object newValue = property.readPropertyDirectly(object());
+ Object newValue = property.readPropertyDirectly(object);
if (newValue instanceof Fault) {
return true;
}
@@ -410,7 +411,7 @@ public class ObjectDiff extends NodeDiff {
@Override
public boolean visitAttribute(AttributeProperty property) {
- Object newValue = property.readProperty(object());
+ Object newValue = property.readProperty(object);
// no baseline to compare
if (snapshot == null) {
diff --git
a/cayenne/src/main/java/org/apache/cayenne/access/ObjectMapRetainStrategy.java
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectMapRetainStrategy.java
index 3749298d0..8d1e4fbb9 100644
---
a/cayenne/src/main/java/org/apache/cayenne/access/ObjectMapRetainStrategy.java
+++
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectMapRetainStrategy.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.access;
import java.util.Map;
-import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
/**
* A strategy for retaining objects in {@link ObjectStore}. The strategy can
be weak, soft
@@ -30,5 +30,5 @@ import org.apache.cayenne.ObjectId;
*/
public interface ObjectMapRetainStrategy {
- Map<ObjectId, ObjectStoreEntry> createObjectMap();
+ Map<Object, Persistent> createObjectMap();
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
index ff7f2facd..0dcdc7aa1 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStore.java
@@ -53,7 +53,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.ConcurrentHashMap;
/**
* ObjectStore stores objects using their ObjectId as a key. It works as a
dedicated
@@ -65,16 +65,14 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class ObjectStore implements Serializable, SnapshotEventListener,
GraphManager {
- protected Map<ObjectId, ObjectStoreEntry> objectMap;
+ protected Map<Object, Persistent> objectMap;
protected Map<Object, ObjectDiff> changes;
/**
* Map that tracks flattened paths for given object Id that is present in
db.
* Presence of path in this map is used to separate insert from update
case of flattened records.
* @since 4.1
- * @deprecated since 5.0 unused
*/
- @Deprecated
protected Map<Object, Map<CayennePath, ObjectId>> trackedFlattenedPaths;
// a sequential id used to tag GraphDiffs so that they can later be sorted
in the
@@ -108,7 +106,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
*
* @since 3.0
*/
- public ObjectStore(DataRowStore dataRowCache, Map<ObjectId,
ObjectStoreEntry> objectMap) {
+ public ObjectStore(DataRowStore dataRowCache, Map<Object, Persistent>
objectMap) {
setDataRowCache(dataRowCache);
if (objectMap != null) {
this.objectMap = objectMap;
@@ -139,7 +137,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
Collection<GraphDiff> getLifecycleEventInducedChanges() {
return lifecycleEventInducedChanges != null
? lifecycleEventInducedChanges
- : Collections.emptyList();
+ : Collections.<GraphDiff>emptyList();
}
void registerLifecycleEventInducedChange(GraphDiff diff) {
@@ -167,13 +165,11 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
if (objectDiff == null) {
- ObjectStoreEntry entry = objectMap.get((ObjectId)nodeId);
- if (entry == null || !entry.hasObject()) {
+ Persistent object = objectMap.get(nodeId);
+ if (object == null) {
throw new CayenneRuntimeException("No object is registered in
context with Id %s", nodeId);
}
- Persistent object = entry.persistent();
-
if (object.getPersistenceState() == PersistenceState.COMMITTED) {
object.setPersistenceState(PersistenceState.MODIFIED);
@@ -200,7 +196,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
}
}
- objectDiff = new ObjectDiff(entry);
+ objectDiff = new ObjectDiff(object);
objectDiff.setDiffId(++currentDiffId);
changes.put(nodeId, objectDiff);
}
@@ -218,13 +214,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
* @since 1.2
*/
public int registeredObjectsCount() {
- AtomicInteger counter = new AtomicInteger();
- objectMap.forEach((id, obj) -> {
- if(obj.hasObject()){
- counter.incrementAndGet();
- }
- });
- return counter.get();
+ return objectMap.size();
}
/**
@@ -293,7 +283,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
*/
// this method is exactly the same as "objectsInvalidated", only
additionally it
// throws out registered objects
- public synchronized void objectsUnregistered(Collection<?> objects) {
+ public synchronized void objectsUnregistered(Collection objects) {
if (objects.isEmpty()) {
return;
}
@@ -308,6 +298,9 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
// remove object but not snapshot
objectMap.remove(id);
changes.remove(id);
+ if(id != null && trackedFlattenedPaths != null) {
+ trackedFlattenedPaths.remove(id);
+ }
ids.add(id);
object.setObjectContext(null);
@@ -321,10 +314,10 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
// send an event for removed snapshots
getDataRowCache().processSnapshotChanges(
this,
- Collections.emptyMap(),
- Collections.emptyList(),
+ Collections.<ObjectId, DataRow>emptyMap(),
+ Collections.<ObjectId>emptyList(),
ids,
- Collections.emptyList());
+ Collections.<ObjectId>emptyList());
}
}
@@ -393,11 +386,11 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
for (Object id : changes.keySet()) {
- ObjectStoreEntry object = objectMap.get((ObjectId)id);
+ Persistent object = objectMap.get(id);
// assume that no new or deleted objects are present (as otherwise
commit
// wouldn't have been phantom).
-
object.persistent().setPersistenceState(PersistenceState.COMMITTED);
+ object.setPersistenceState(PersistenceState.COMMITTED);
}
// clear caches
@@ -412,10 +405,8 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
public void postprocessAfterCommit(GraphDiff parentChanges) {
// scan through changed objects, set persistence state to committed
- for (Object key : changes.keySet()) {
- ObjectId id = (ObjectId) key;
- // persistent object for the diff should always exist
- Persistent object = objectMap.get(id).persistent();
+ for (Object id : changes.keySet()) {
+ Persistent object = objectMap.get(id);
switch (object.getPersistenceState()) {
case PersistenceState.DELETED:
@@ -512,7 +503,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
* Returns an iterator over the registered objects.
*/
public synchronized Iterator<Persistent> getObjectIterator() {
- return new EntryIterator(objectMap.values().iterator());
+ return objectMap.values().iterator();
}
/**
@@ -533,9 +524,9 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
public synchronized List<Persistent> objectsInState(int state) {
List<Persistent> filteredObjects = new ArrayList<>();
- for (ObjectStoreEntry entry : objectMap.values()) {
- if (entry.hasObject() && entry.persistent().getPersistenceState()
== state) {
- filteredObjects.add(entry.persistent());
+ for (Persistent object : objectMap.values()) {
+ if (object.getPersistenceState() == state) {
+ filteredObjects.add(object);
}
}
@@ -595,21 +586,11 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
}
void processIdChange(Object nodeId, Object newId) {
- ObjectStoreEntry entry = objectMap.remove((ObjectId)nodeId);
-
- if (entry != null) {
- ObjectId id = (ObjectId) newId;
- entry.persistent().setObjectId(id);
- objectMap.merge(id, entry, (oldValue, newValue) -> {
- if(oldValue.trackedFlattenedPaths != null) {
- if(newValue.trackedFlattenedPaths != null) {
-
newValue.trackedFlattenedPaths.putAll(oldValue.trackedFlattenedPaths);
- } else {
- newValue.trackedFlattenedPaths =
oldValue.trackedFlattenedPaths;
- }
- }
- return newValue;
- });
+ Persistent object = objectMap.remove(nodeId);
+
+ if (object != null) {
+ object.setObjectId((ObjectId) newId);
+ objectMap.put(newId, object);
ObjectDiff change = changes.remove(nodeId);
if (change != null) {
@@ -617,6 +598,12 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
}
}
+ if(trackedFlattenedPaths != null) {
+ Map<CayennePath, ObjectId> paths =
trackedFlattenedPaths.remove(nodeId);
+ if(paths != null) {
+ trackedFlattenedPaths.put(newId, paths);
+ }
+ }
}
/**
@@ -627,10 +614,9 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
void processDeletedID(ObjectId nodeId) {
// access object map directly - the method should be called in a
synchronized context...
- ObjectStoreEntry entry = objectMap.get(nodeId);
+ Persistent object = objectMap.get(nodeId);
- if (entry != null && entry.hasObject()) {
- Persistent object = entry.persistent();
+ if (object != null) {
DataContextDelegate delegate;
switch (object.getPersistenceState()) {
@@ -726,14 +712,11 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
void processIndirectlyModifiedIDs(Collection<ObjectId>
indirectlyModifiedIDs) {
for (ObjectId oid : indirectlyModifiedIDs) {
// access object map directly - the method should be called in a
synchronized context...
- ObjectStoreEntry entry = objectMap.get(oid);
+ final Persistent object = objectMap.get(oid);
- if (entry == null
- || !entry.hasObject()
- || entry.persistent().getPersistenceState() !=
PersistenceState.COMMITTED) {
+ if (object == null || object.getPersistenceState() !=
PersistenceState.COMMITTED) {
continue;
}
- Persistent object = entry.persistent();
// for now break all "independent" object relationships...
// in the future we may want to be more precise and go after
modified
@@ -783,12 +766,11 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
void processUpdatedSnapshot(ObjectId nodeId, DataRow diff) {
// access object map directly - the method should be called in a
synchronized context...
- ObjectStoreEntry entry = objectMap.get(nodeId);
+ Persistent object = objectMap.get(nodeId);
// no object, or HOLLOW object require no processing
- if (entry != null && entry.hasObject()) {
+ if (object != null) {
- Persistent object = entry.persistent();
int state = object.getPersistenceState();
if (state != PersistenceState.HOLLOW) {
@@ -862,12 +844,13 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
* @since 1.2
*/
@Override
- public synchronized Persistent getNode(Object nodeId) {
- ObjectStoreEntry entry = objectMap.get((ObjectId) nodeId);
- if(entry == null) {
- return null;
- }
- return entry.persistent();
+ public synchronized Object getNode(Object nodeId) {
+ return objectMap.get(nodeId);
+ }
+
+ // non-synchronized version of getNode for private use
+ final Object getNodeNoSync(Object nodeId) {
+ return objectMap.get(nodeId);
}
/**
@@ -878,13 +861,7 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
*/
@Override
public synchronized Collection<Object> registeredNodes() {
- List<Object> values = new ArrayList<>(objectMap.size());
- objectMap.forEach((id, entry) -> {
- if(entry.hasObject()) {
- values.add(entry.persistent());
- }
- });
- return values;
+ return new ArrayList<Object>(objectMap.values());
}
/**
@@ -892,15 +869,15 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
*/
@Override
public synchronized void registerNode(Object nodeId, Object nodeObject) {
- objectMap.put((ObjectId)nodeId, new ObjectStoreEntry((Persistent)
nodeObject));
+ objectMap.put(nodeId, (Persistent) nodeObject);
}
/**
* @since 1.2
*/
@Override
- public synchronized Persistent unregisterNode(Object nodeId) {
- Persistent object = getNode(nodeId);
+ public synchronized Object unregisterNode(Object nodeId) {
+ Object object = getNode(nodeId);
if (object != null) {
objectsUnregistered(Collections.singleton(object));
}
@@ -998,28 +975,52 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
registerDiff(nodeId, diff);
}
+ /**
+ * Check that flattened path for given object ID has data row in DB.
+ * @since 4.1
+ */
+ boolean hasFlattenedPath(ObjectId objectId, CayennePath path) {
+ if(trackedFlattenedPaths == null) {
+ return false;
+ }
+ return trackedFlattenedPaths
+ .getOrDefault(objectId,
Collections.emptyMap()).containsKey(path);
+ }
+
/**
* @since 4.2
*/
public ObjectId getFlattenedId(ObjectId objectId, CayennePath path) {
- ObjectStoreEntry entry = objectMap.get(objectId);
- return entry == null ? null : entry.getFlattenedId(path);
+ if(trackedFlattenedPaths == null) {
+ return null;
+ }
+
+ return trackedFlattenedPaths
+ .getOrDefault(objectId, Collections.emptyMap()).get(path);
}
/**
* @since 4.2
*/
public Collection<ObjectId> getFlattenedIds(ObjectId objectId) {
- ObjectStoreEntry entry = objectMap.get(objectId);
- return entry == null ? null : entry.getFlattenedIds();
+ if(trackedFlattenedPaths == null) {
+ return Collections.emptyList();
+ }
+
+ return trackedFlattenedPaths
+ .getOrDefault(objectId, Collections.emptyMap()).values();
}
/**
* @since 5.0
*/
- public Map<CayennePath, ObjectId> getFlattenedPathIdMap(ObjectId objectId)
{
- ObjectStoreEntry entry = objectMap.get(objectId);
- return entry == null ? null : entry.getFlattenedPathIdMap();
+ public Map<CayennePath,ObjectId> getFlattenedPathIdMap(ObjectId objectId) {
+ if(trackedFlattenedPaths == null) {
+ return Collections.emptyMap();
+ }
+
+ return trackedFlattenedPaths
+ .getOrDefault(objectId, Collections.emptyMap());
}
/**
@@ -1027,8 +1028,12 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
* @since 4.1
*/
public void markFlattenedPath(ObjectId objectId, CayennePath path,
ObjectId id) {
- objectMap.computeIfAbsent(objectId, objId -> new
ObjectStoreEntry(null))
- .markFlattenedPath(path, id);
+ if(trackedFlattenedPaths == null) {
+ trackedFlattenedPaths = new ConcurrentHashMap<>();
+ }
+ trackedFlattenedPaths
+ .computeIfAbsent(objectId, o -> new ConcurrentHashMap<>())
+ .put(path, id);
}
// an ObjectIdQuery optimized for retrieval of multiple snapshots - it can
be reset
@@ -1072,28 +1077,4 @@ public class ObjectStore implements Serializable,
SnapshotEventListener, GraphMa
throw new UnsupportedOperationException();
}
}
-
- static class EntryIterator implements Iterator<Persistent> {
-
- final Iterator<ObjectStoreEntry> iterator;
-
- EntryIterator(Iterator<ObjectStoreEntry> iterator) {
- this.iterator = iterator;
- }
-
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- @Override
- public Persistent next() {
- return iterator.next().persistent();
- }
-
- @Override
- public void remove() {
- iterator.remove();
- }
- }
}
diff --git
a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreEntry.java
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreEntry.java
deleted file mode 100644
index 8aa0a3261..000000000
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreEntry.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * https://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. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
-package org.apache.cayenne.access;
-
-import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.Persistent;
-import org.apache.cayenne.exp.path.CayennePath;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @since 5.0
- */
-public class ObjectStoreEntry implements Serializable {
-
- final protected Persistent persistent;
- protected Map<CayennePath, ObjectId> trackedFlattenedPaths;
-
- public ObjectStoreEntry(Persistent persistent) {
- this.persistent = persistent;
- }
-
- public Persistent persistent() {
- return persistent;
- }
-
- public boolean hasObject() {
- return persistent != null;
- }
-
- public void markFlattenedPath(CayennePath path, ObjectId objectId) {
- if (trackedFlattenedPaths == null) {
- trackedFlattenedPaths = new ConcurrentHashMap<>();
- }
- trackedFlattenedPaths.put(path, objectId);
- }
-
- public ObjectId getFlattenedId(CayennePath path) {
- return trackedFlattenedPaths == null ? null :
trackedFlattenedPaths.get(path);
- }
-
- public Collection<ObjectId> getFlattenedIds() {
- return trackedFlattenedPaths == null ? Collections.emptyList() :
trackedFlattenedPaths.values();
- }
-
- public Map<CayennePath, ObjectId> getFlattenedPathIdMap() {
- return trackedFlattenedPaths == null ? Collections.emptyMap() :
trackedFlattenedPaths;
- }
-}
diff --git
a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
index 0208cf5ea..3043fa403 100644
--- a/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
+++ b/cayenne/src/main/java/org/apache/cayenne/access/ObjectStoreGraphDiff.java
@@ -70,7 +70,8 @@ public class ObjectStoreGraphDiff implements GraphDiff {
boolean noop = true;
// build a new collection for validation as validation methods may
- // result in ObjectStore modifications
+ // result in
+ // ObjectStore modifications
Collection<Validating> objectsToValidate = null;
@@ -80,12 +81,12 @@ public class ObjectStoreGraphDiff implements GraphDiff {
noop = false;
- if (diff.object() instanceof Validating) {
+ if (diff.getObject() instanceof Validating) {
if (objectsToValidate == null) {
objectsToValidate = new ArrayList<>();
}
- objectsToValidate.add((Validating) diff.object());
+ objectsToValidate.add((Validating) diff.getObject());
}
}
diff --git
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextPrefetchMultistepIT.java
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextPrefetchMultistepIT.java
index 897d60f53..7bc9eab7b 100644
---
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextPrefetchMultistepIT.java
+++
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextPrefetchMultistepIT.java
@@ -113,7 +113,7 @@ public class DataContextPrefetchMultistepIT extends
RuntimeCase {
// get garbage collected, and we won't be able to detect them
// so ensure ObjectStore uses a regular map just for this test
- context.getObjectStore().objectMap = new HashMap<>();
+ context.getObjectStore().objectMap = new HashMap<Object, Persistent>();
// Check the target ArtistExhibit objects do not exist yet
diff --git
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java
index face100de..441a9f8e9 100644
---
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java
+++
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java
@@ -21,8 +21,8 @@ package org.apache.cayenne.access;
import org.apache.cayenne.Cayenne;
import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.ObjectId;
import org.apache.cayenne.PersistenceState;
+import org.apache.cayenne.Persistent;
import org.apache.cayenne.runtime.CayenneRuntime;
import org.apache.cayenne.configuration.DefaultRuntimeProperties;
import org.apache.cayenne.di.Inject;
@@ -152,7 +152,7 @@ public class DataContextSerializationIT extends RuntimeCase
{
new DefaultRuntimeProperties(domain.getProperties()),
domain.getEventManager());
- Map<ObjectId, ObjectStoreEntry> map = new HashMap<>();
+ Map<Object, Persistent> map = new HashMap<>();
DataContext localCacheContext = new DataContext(domain, new
ObjectStore(
snapshotCache,
diff --git
a/cayenne/src/test/java/org/apache/cayenne/access/ObjectStoreTest.java
b/cayenne/src/test/java/org/apache/cayenne/access/ObjectStoreTest.java
index b25336196..e79770498 100644
--- a/cayenne/src/test/java/org/apache/cayenne/access/ObjectStoreTest.java
+++ b/cayenne/src/test/java/org/apache/cayenne/access/ObjectStoreTest.java
@@ -42,7 +42,7 @@ public class ObjectStoreTest {
@Before
public void before() {
DataRowStore sharedCache = mock(DataRowStore.class);
- this.objectStore = new ObjectStore(sharedCache, new HashMap<>());
+ this.objectStore = new ObjectStore(sharedCache, new HashMap<Object,
Persistent>());
}
@Test