This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch better-page-invalidation
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


The following commit(s) were added to refs/heads/better-page-invalidation by 
this push:
     new db8a6f3fe TAP5-2742: handling page dependencies better (or at least 
trying)
db8a6f3fe is described below

commit db8a6f3fee947b2246ce430da36c4910ce493a29
Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
AuthorDate: Thu May 25 18:55:50 2023 -0300

    TAP5-2742: handling page dependencies better (or at least trying)
---
 .../services/ComponentDependencyRegistryImpl.java  | 67 ++++++--------------
 .../services/ComponentInstantiatorSourceImpl.java  | 11 +++-
 .../internal/services/PageSourceImpl.java          | 73 +++++++++++++++-------
 .../apache/tapestry5/modules/TapestryModule.java   |  7 ++-
 .../pageload/PageClassloaderContextManager.java    |  5 +-
 .../PageClassloaderContextManagerImpl.java         | 54 ++++++++++++----
 6 files changed, 126 insertions(+), 91 deletions(-)

diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java
index 92a41e34b..5231ff8a0 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyRegistryImpl.java
@@ -52,6 +52,7 @@ import 
org.apache.tapestry5.internal.structure.ComponentPageElement;
 import org.apache.tapestry5.ioc.Orderable;
 import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.services.PerthreadManager;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.model.EmbeddedComponentModel;
@@ -68,6 +69,8 @@ import org.slf4j.Logger;
 public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegistry 
 {
     
+    private static final List<String> EMPTY_LIST = Collections.emptyList();
+
     final private PageClassloaderContextManager pageClassloaderContextManager;
     
     private static final String META_ATTRIBUTE = 
"injectedComponentDependencies";
@@ -151,6 +154,13 @@ public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegis
         
     }
     
+    public void setupThreadCleanup(final PerthreadManager perthreadManager)
+    {
+        perthreadManager.addThreadCleanupCallback(() -> {
+            INVALIDATIONS_DISABLED.set(0);
+        });
+    }
+    
     @Override
     public void register(Class<?> component) 
     {
@@ -584,14 +594,14 @@ public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegis
     // Protected just for testing
     List<String> listen(List<String> resources)
     {
-        List<String> furtherDependents;
-        if (INVALIDATIONS_DISABLED.get() > 0)
+        List<String> furtherDependents = EMPTY_LIST;
+        if (resources.isEmpty())
         {
-            furtherDependents = Collections.emptyList();
+            clear();
+            furtherDependents = EMPTY_LIST;
         }
-        else if (resources.isEmpty())
+        else if (INVALIDATIONS_DISABLED.get() > 0)
         {
-            clear();
             furtherDependents = Collections.emptyList();
         }
         // Don't invalidate component dependency information when 
@@ -613,12 +623,9 @@ public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegis
                 }
                 
                 clear(resource);
+                
             }
         }
-        else
-        {
-            furtherDependents = Collections.emptyList();
-        }
         return furtherDependents;
     }
 
@@ -688,6 +695,10 @@ public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegis
     public void enableInvalidations() 
     {
         INVALIDATIONS_DISABLED.set(INVALIDATIONS_DISABLED.get() - 1);
+        if (INVALIDATIONS_DISABLED.get() < 0)
+        {
+            INVALIDATIONS_DISABLED.set(0);
+        }
     }
 
     /**
@@ -848,44 +859,6 @@ public class ComponentDependencyRegistryImpl implements 
ComponentDependencyRegis
         }
 
     }
-
-    final private class InvalidationOnlyDependency
-    {
-        
-        private String className;
-        private String dependency;
-        
-        public InvalidationOnlyDependency(String className, String dependency) 
-        {
-            super();
-            this.className = className;
-            this.dependency = dependency;
-        }
-
-        @Override
-        public int hashCode() 
-        {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + Objects.hash(className, dependency);
-            return result;
-        }
-        
-        @Override
-        public boolean equals(Object obj) 
-        {
-            if (this == obj) 
-            {
-                return true;
-            }
-            if (!(obj instanceof InvalidationOnlyDependency)) {
-                return false;
-            }
-            InvalidationOnlyDependency other = (InvalidationOnlyDependency) 
obj;
-            return Objects.equals(className, other.className) && 
Objects.equals(dependency, other.dependency);
-        }
-        
-    }
     
     private static final class Dependency
     {
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
index bfafdeeb1..4d0fa42ea 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java
@@ -341,8 +341,15 @@ public final class ComponentInstantiatorSourceImpl 
implements ComponentInstantia
                         OPEN_INSTANTIATORS.get().add(className);
                         
                         componentDependencyRegistry.disableInvalidations();
-                        PageClassloaderContext context = 
pageClassloaderContextManager.get(className);
-                        componentDependencyRegistry.enableInvalidations();
+                        PageClassloaderContext context;
+                        try
+                        {
+                            context = 
pageClassloaderContextManager.get(className);
+                        }
+                        finally
+                        {
+                            componentDependencyRegistry.enableInvalidations();
+                        }
                         
                         // Make sure the dependencies have been processed in 
case
                         // there was some invalidation going on and they're 
not there.
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
index 5d9dd16e5..ebf86306e 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
@@ -118,7 +118,21 @@ public class PageSourceImpl implements PageSource
     
     public Page getPage(String canonicalPageName)
     {
-        return getPage(canonicalPageName, true);
+        if (!productionMode)
+        {
+            componentDependencyRegistry.disableInvalidations();
+        }
+        try
+        {
+            return getPage(canonicalPageName, true);
+        }
+        finally
+        {
+            if (!productionMode)
+            {
+                componentDependencyRegistry.enableInvalidations();
+            }
+        }
     }
 
     public Page getPage(String canonicalPageName, boolean 
invalidateUnknownContext)
@@ -131,11 +145,6 @@ public class PageSourceImpl implements PageSource
         // with all of its mutable construction-time state, is properly 
published to other
         // threads (at least, as I understand Brian Goetz's explanation, it 
should be).
         
-        if (!productionMode && invalidateUnknownContext)
-        {
-            componentDependencyRegistry.disableInvalidations();
-        }
-
         while (true)
         {
             SoftReference<Page> ref = pageCache.get(key);
@@ -144,10 +153,6 @@ public class PageSourceImpl implements PageSource
 
             if (page != null)
             {
-                if (invalidateUnknownContext && !productionMode)
-                {
-                    componentDependencyRegistry.enableInvalidations();
-                }
                 return page;
             }
             
@@ -184,11 +189,19 @@ public class PageSourceImpl implements PageSource
                 componentDependencyRegistry.clear(rootElement);
                 componentDependencyRegistry.register(rootElement);
                 PageClassloaderContext context = 
pageClassloaderContextManager.get(className);
-                if (invalidateUnknownContext && context.isUnknown())
+                
+                if (context.isUnknown())
                 {
-                    
pageClassloaderContextManager.invalidateAndFireInvalidationEvents(context);
-                    pageClassloaderContextManager.get(className);
-                    preprocessPageDependencies(className);
+                    this.pageCache.remove(key);
+                    if (invalidateUnknownContext)
+                    {
+//                        pageClassloaderContextManager.invalidate(context);
+                        
pageClassloaderContextManager.invalidateAndFireInvalidationEvents(context);
+                        preprocessPageDependencies(className);
+                    }
+//                    context.getClassNames().remove(className);
+                    context.getClassNames().clear();
+                    // Avoiding bad invalidations
                     return getPage(canonicalPageName, false);
                 }
             }
@@ -224,18 +237,30 @@ public class PageSourceImpl implements PageSource
             pageClassloaderContextManager.get(className);
             for (String pageClassName : pageDependencies)
             {
-                pageClassloaderContextManager.get(pageClassName);
+                final PageClassloaderContext context = 
pageClassloaderContextManager.get(pageClassName);
+                if (i == 1)
+                {
+                    try 
+                    {
+                        context.getClassLoader().loadClass(pageClassName);
+                    } catch (ClassNotFoundException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
             }
         }
-    }
-
-    private Class<?> getSuperclass(final String className, 
PageClassloaderContext context) 
-    {
-        try {
-            return 
context.getClassLoader().loadClass(className).getSuperclass();
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException(e);
-        }
+        
+        // TODO: remove
+//        for (String pageClassName : pageDependencies)
+//        {
+//            try 
+//            {
+//                
pageClassloaderContextManager.get(pageClassName).getClassLoader().loadClass(pageClassName);
+//            } catch (ClassNotFoundException e) 
+//            {
+//                throw new RuntimeException(e);
+//            }
+//        }
     }
 
     @PostInjection
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 5c57f9e57..b044523be 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -2791,9 +2791,10 @@ public final class TapestryModule
             ComponentInstantiatorSource componentInstantiatorSource,
             ComponentClassResolver componentClassResolver,
             TemplateParser templateParser,
-            ComponentTemplateLocator componentTemplateLocator)
+            ComponentTemplateLocator componentTemplateLocator,
+            PerthreadManager perthreadManager)
     {
-        ComponentDependencyRegistry componentDependencyRegistry = 
+        ComponentDependencyRegistryImpl componentDependencyRegistry = 
                 new ComponentDependencyRegistryImpl(
                         pageClassloaderContextManager,
                         
componentInstantiatorSource.getProxyFactory().getPlasticManager(),
@@ -2803,6 +2804,8 @@ public final class TapestryModule
         
componentDependencyRegistry.listen(internalComponentInvalidationEventHub);
         componentDependencyRegistry.listen(resourceChangeTracker);
         
componentDependencyRegistry.listen(componentTemplateSource.getInvalidationEventHub());
+        // TODO: remove
+        componentDependencyRegistry.setupThreadCleanup(perthreadManager);
         return componentDependencyRegistry;
     }
     
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManager.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManager.java
index 81b3b6167..375d0526f 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManager.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManager.java
@@ -85,9 +85,8 @@ public interface PageClassloaderContextManager
     Class<?> getClassInstance(Class<?> clasz, String pageName);
 
     /**
-     * Invalidates the <code>unknown</code> context.
-     * TODO: remove this
+     * Invalidates the "unknown" page classloader context context.
      */
     void invalidateUnknownContext();
-    
+
 }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java
index 9c7cef88b..91241c661 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassloaderContextManagerImpl.java
@@ -82,14 +82,29 @@ public class PageClassloaderContextManagerImpl implements 
PageClassloaderContext
     @Override
     public void invalidateUnknownContext()
     {
-        for (PageClassloaderContext context : root.getChildren())
-        {
-            if (context.isUnknown())
+        synchronized (this) {
+            markAsNotInvalidatingContext();
+            for (PageClassloaderContext context : root.getChildren())
             {
-                componentDependencyRegistry.disableInvalidations();
-                invalidateAndFireInvalidationEvents(context);
-                componentDependencyRegistry.enableInvalidations();
-                break;
+                if (context.isUnknown())
+                {
+//                    componentDependencyRegistry.disableInvalidations();
+//                    final Set<String> classNames = invalidate(context);
+//                    List<String> toInvalidate = new ArrayList<>();
+//                    for (String className : classNames) 
+//                    {
+//                        if (root.findByClassName(className) == null)
+//                        {
+//                            toInvalidate.add(className);
+//                        }
+//                    }
+//                    
componentClassesInvalidationEventHub.fireInvalidationEvent(toInvalidate);
+//                    invalidationHub.fireInvalidationEvent(toInvalidate);
+//                    
+//                    componentDependencyRegistry.enableInvalidations();
+                    invalidateAndFireInvalidationEvents(context);
+                    break;
+                }
             }
         }
     }
@@ -214,8 +229,10 @@ public class PageClassloaderContextManagerImpl implements 
PageClassloaderContext
                 context = root;
             } else {
                 if (
-                        !componentDependencyRegistry.contains(className) && 
-                        
componentDependencyRegistry.getDependents(className).isEmpty())
+                        !componentDependencyRegistry.contains(className) 
+                        // TODO: review this
+//                        && 
componentDependencyRegistry.getDependents(className).isEmpty()
+                        )
                 {
                     context = unknownContextProvider.get();
 //                    // Make sure you get a fresh version of the class before 
processing its
@@ -306,7 +323,8 @@ public class PageClassloaderContextManagerImpl implements 
PageClassloaderContext
                     // Ensure non-page class is initialized in the correct 
context and classloader.
                     // Pages get their own context and classloader, so this 
initialization
                     // is both non-needed and a cause for an NPE if it happens.
-                    if (!componentClassResolver.isPage(className))
+                    if (!componentClassResolver.isPage(className)
+                            || 
componentDependencyRegistry.getDependencies(className, 
DependencyType.USAGE).isEmpty())
                     {
                         loadClass(className, context);
                     }
@@ -547,21 +565,31 @@ public class PageClassloaderContextManagerImpl implements 
PageClassloaderContext
     @Override
     public void invalidateAndFireInvalidationEvents(PageClassloaderContext... 
contexts) {
         final Set<String> classNames = invalidate(contexts);
-        INVALIDATING_CONTEXT.set(true);
+        markAsInvalidatingContext();
         invalidate(classNames);
+        markAsNotInvalidatingContext();
+    }
+
+    private void markAsNotInvalidatingContext() {
+//        System.out.println("XXXX Mark as NOT invalidating. Current: " + 
INVALIDATING_CONTEXT.get());
         INVALIDATING_CONTEXT.set(false);
     }
+
+    private void markAsInvalidatingContext() {
+//        System.out.println("XXXX Mark as invalidating. Current: " + 
INVALIDATING_CONTEXT.get());
+        INVALIDATING_CONTEXT.set(true);
+    }
     
     private void invalidate(Set<String> classesToInvalidate) {
         if (!classesToInvalidate.isEmpty())
         {
             LOGGER.debug("Invalidating classes {}", classesToInvalidate);
-            INVALIDATING_CONTEXT.set(true);
+            markAsInvalidatingContext();
             final ArrayList<String> classesToInvalidateAsList = new 
ArrayList<>(classesToInvalidate);
             // TODO: do we really need both invalidation hubs to be invoked 
here?
             invalidationHub.fireInvalidationEvent(classesToInvalidateAsList);
             
componentClassesInvalidationEventHub.fireInvalidationEvent(classesToInvalidateAsList);
-            INVALIDATING_CONTEXT.set(false);
+            markAsNotInvalidatingContext();
         }
     }
 

Reply via email to