This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 312503 - Core: IdentityMapAccessor.invalidateClass() should invalidate a subtree when recurse is false
Summary: Core: IdentityMapAccessor.invalidateClass() should invalidate a subtree when ...
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL: http://wiki.eclipse.org/EclipseLink/D...
Whiteboard:
Keywords:
Depends on:
Blocks: 312311 248780
  Show dependency tree
 
Reported: 2010-05-11 16:24 EDT by Michael OBrien CLA
Modified: 2022-06-09 10:18 EDT (History)
1 user (show)

See Also:
michael.f.obrien: documentation+


Attachments
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree (1.46 KB, patch)
2010-05-11 17:02 EDT, Michael OBrien CLA
no flags Details | Diff
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree (1.46 KB, patch)
2010-05-11 17:03 EDT, Michael OBrien CLA
no flags Details | Diff
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree (6.58 KB, patch)
2010-05-31 11:34 EDT, Michael OBrien CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael OBrien CLA 2010-05-11 16:24:14 EDT
>Invalidating a cache object either invalidates the entire tree to the root (recurse=true)
or invalidates a single entity (recurse=false)
>The issue is we do not have the capability to invalidate a subtree starting at the invalidation class.
in the following code when the recurse flag is false - we

IdentityMapAccessor.java:820
    public void invalidateClass(Class myClass, boolean recurse) {
      if (recurse || ((obj != null) && myClass.isInstance(obj)){                
           key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);

>Discussed this with James and we should align the code with what is done in
IdentityMapManager.invalidateObject():581
      if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
          key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);

>by using isInstance() instead of equals()

The following model illustrates this issue when we attempt to invalidate at different levels in the inheritance tree

Class1 (non-persistable java class)
  +---Entity2 (abstract entity)
        +--- MappedSuperclass3 (MappedSuperclass)
               +-----Entity4a (concrete entity)
                       +--- Class5 (non-persistable java class)
               +-----Entity4b (concrete entity)

>currently if we evict() any of Class1 down to Class5 
we evict the entire inheritance tree from Entity2 in all cases
- This is because getIdentityMap(Class5 or any other) will return the identityMap for the root entity (Entity2) in all cases - by design

Where the existing code becomes an issue is if we wish to invalidate only a subtree of the root descriptor by using recurse=false
Comment 1 Michael OBrien CLA 2010-05-11 16:38:45 EDT
>Existing code is 
IdentityMapAccessor.java:820
    public void invalidateClass(Class myClass, boolean recurse) {
      if(recurse || ((obj != null) && obj.getClass().equals(myClass)){                
           key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
Comment 2 Michael OBrien CLA 2010-05-11 17:02:04 EDT
Created attachment 168037 [details]
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree
Comment 3 Michael OBrien CLA 2010-05-11 17:03:59 EDT
Created attachment 168038 [details]
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree
Comment 4 Michael OBrien CLA 2010-05-12 09:30:17 EDT
>The following model is used to to illustrate use case behavior when invalidating non-entity classes 
(extended functionality beyond the JPA specification) in an inheritance hierarchy.

Class1 (non-persistable java class)
  +---Entity2 (abstract entity)
        +--- MappedSuperclass3 (MappedSuperclass)
               +-----Entity4a (concrete entity)
                       +--- Class5 (non-persistable java class)
               +-----Entity4b (concrete entity)

Entity4a and Entity4b are in the cache to start.
>Here is the current behavior (all evict operations evict the entire tree)
- This is because getIdentityMap(Class5 or any other) will return the identityMap for the root entity (Entity2) in all cases - by design
evict(Class1)            --> evicts E4a and E4b
evict(Entity2)           --> evicts E4a and E4b
evict(MappedSuperclass3) --> evicts E4a and E4b
evict(Entity4a)          --> evicts E4a and E4b
evict(Class5)            --> evicts E4a and E4b
evict(Entity4b)          --> evicts E4a and E4b

>I propose that we introduce more granular eviction behavior by not always evicting the root
- but by evicting the subtree
evict(Class1)            --> evicts E4a and E4b
evict(Entity2)           --> evicts E4a and E4b
evict(MappedSuperclass3) --> evicts E4a and E4b
evict(Entity4a)          --> evicts E4a only
evict(Class5)            --> evicts E4a only
evict(Entity4b)          --> evicts E4b only

>Part of the change to enable this behavior is fixing the invalidateClass() function for cases where recurse=false
See bug# 312503
- we may add a 2nd flag [recurseSubTree) to make the invalidateClass(Class) function (tri/quad state)
recurse recurseSubtree behavior
-------------------------------
false   false          :invalidate only class parameter - existing equals functionality
false   true           :invalidate subtree from Class parameter - new isAssignableFrom functionality
true    false(x)       :invalidate entire tree from root
true    true(x)        :invalidate entire tree from root
Comment 5 Michael OBrien CLA 2010-05-31 11:34:54 EDT
Created attachment 170542 [details]
IdentityMapAccessor.invalidateClass() refactor to invalidate subtree

>The test suite used by the Cache API in bug# 248780 has sufficient inheritance levels for testing this change
>The existing Project model suite passes with/without this change - as it is 1 level deep
Comment 6 Michael OBrien CLA 2010-05-31 11:40:13 EDT
>A documentation release note is required
- previously when the (non-default) recurse flag of false was used - only the single class inside the tree was invalidated
- now the entire subtree is invalidated 
- using the default behaviour of recurse=true has unaffected functionality - and removes the entire tree up to the root
Comment 7 Michael OBrien CLA 2010-06-03 10:06:49 EDT
>see SVN rev# 7447
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:18:45 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink