Author: mduerig
Date: Wed Jan  8 10:39:42 2014
New Revision: 1556488

URL: http://svn.apache.org/r1556488
Log:
OAK-941 MBean to track sessions
Defer session MBean registrations to avoid cluttering the JMX name space with 
short lived sessions

Modified:
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
    
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
    
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java?rev=1556488&r1=1556487&r2=1556488&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java
 Wed Jan  8 10:39:42 2014
@@ -20,6 +20,9 @@ import static com.google.common.base.Pre
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -32,11 +35,17 @@ import javax.jcr.SimpleCredentials;
 import javax.jcr.Value;
 import javax.security.auth.login.LoginException;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableScheduledFuture;
+import com.google.common.util.concurrent.ListeningScheduledExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 import org.apache.jackrabbit.api.JackrabbitRepository;
 import 
org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.jmx.SessionMBean;
 import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.LogOnce;
@@ -44,8 +53,11 @@ import org.apache.jackrabbit.oak.jcr.ses
 import 
org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.ThreadSynchronising;
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy.Timed;
 import org.apache.jackrabbit.oak.jcr.session.SessionContext;
+import org.apache.jackrabbit.oak.jcr.session.SessionStats;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
 import org.apache.jackrabbit.oak.util.GenericDescriptors;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -73,6 +85,8 @@ public class RepositoryImpl implements J
     protected final Whiteboard whiteboard;
     private final SecurityProvider securityProvider;
     private final ThreadLocal<Long> threadSaveCount;
+    private final ListeningScheduledExecutorService scheduledExecutor =
+            
MoreExecutors.listeningDecorator(Executors.newSingleThreadScheduledExecutor());
 
     public RepositoryImpl(@Nonnull ContentRepository contentRepository,
                           @Nonnull Whiteboard whiteboard,
@@ -206,7 +220,7 @@ public class RepositoryImpl implements J
 
             RefreshStrategy refreshStrategy = 
createRefreshStrategy(refreshInterval);
             ContentSession contentSession = 
contentRepository.login(credentials, workspaceName);
-            SessionDelegate sessionDelegate = new 
SessionDelegate(contentSession, refreshStrategy);
+            SessionDelegate sessionDelegate = 
createSessionDelegate(refreshStrategy, contentSession);
             SessionContext context = createSessionContext(
                     securityProvider, createAttributes(refreshInterval), 
sessionDelegate);
             return context.getSession();
@@ -215,9 +229,39 @@ public class RepositoryImpl implements J
         }
     }
 
+    private SessionDelegate createSessionDelegate(
+            final RefreshStrategy refreshStrategy,
+            final ContentSession contentSession) {
+        return new SessionDelegate(contentSession, refreshStrategy) {
+            // Defer session MBean registration to avoid cluttering the
+            // JMX name space with short lived sessions
+            ListenableScheduledFuture<Registration> registration = 
scheduledExecutor.schedule(
+                    new RegistrationCallable(getSessionStats(), whiteboard), 
1, TimeUnit.MINUTES);
+
+            @Override
+            public void logout() {
+                // Cancel session MBean registration and unregister MBean
+                // if registration succeed before the cancellation
+                registration.cancel(false);
+                Futures.addCallback(registration, new 
FutureCallback<Registration>() {
+                    @Override
+                    public void onSuccess(Registration registration) {
+                        registration.unregister();
+                    }
+
+                    @Override
+                    public void onFailure(Throwable t) {
+                    }
+                });
+
+                super.logout();
+            }
+        };
+    }
+
     @Override
     public void shutdown() {
-        // empty
+        scheduledExecutor.shutdown();
     }
 
     //------------------------------------------------------------< internal 
>---
@@ -327,4 +371,19 @@ public class RepositoryImpl implements J
                 new ThreadSynchronising(threadSaveCount)});
     }
 
+    private static class RegistrationCallable implements 
Callable<Registration> {
+        private final SessionStats sessionStats;
+        private final Whiteboard whiteboard;
+
+        public RegistrationCallable(SessionStats sessionStats, Whiteboard 
whiteboard) {
+            this.sessionStats = sessionStats;
+            this.whiteboard = whiteboard;
+        }
+
+        @Override
+        public Registration call() throws Exception {
+            return WhiteboardUtils.registerMBean(whiteboard, 
SessionMBean.class,
+                    sessionStats, SessionMBean.TYPE, sessionStats.toString());
+        }
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java?rev=1556488&r1=1556487&r2=1556488&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
 Wed Jan  8 10:39:42 2014
@@ -42,7 +42,6 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.oak.api.jmx.SessionMBean;
 import org.apache.jackrabbit.oak.jcr.delegate.AccessControlManagerDelegator;
 import 
org.apache.jackrabbit.oak.jcr.delegate.JackrabbitAccessControlManagerDelegator;
 import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
@@ -65,9 +64,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConfiguration;
 import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
-import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
-import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
 import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -102,7 +99,6 @@ public class SessionContext implements N
     private UserManager userManager;
     private PrivilegeManager privilegeManager;
     private ObservationManagerImpl observationManager;
-    private final Registration sessionMBeanRegistration;
 
     /** Paths (tokens) of all open scoped locks held by this session. */
     private final Set<String> openScopedLocks = newTreeSet();
@@ -121,8 +117,6 @@ public class SessionContext implements N
         this.delegate = checkNotNull(delegate);
         SessionStats sessionStats = delegate.getSessionStats();
         sessionStats.setAttributes(attributes);
-        this.sessionMBeanRegistration = 
WhiteboardUtils.registerMBean(whiteboard, SessionMBean.class,
-                sessionStats, SessionMBean.TYPE, sessionStats.toString());
 
         this.namespaces = new SessionNamespaces(this);
         LocalNameMapper nameMapper = new 
LocalNameMapper(delegate.getRoot().getTree("/")) {
@@ -371,7 +365,6 @@ public class SessionContext implements N
     //-----------------------------------------------------------< internal 
>---
 
     void dispose() {
-        sessionMBeanRegistration.unregister();
         try {
             unlockAllSessionScopedLocks();
         } catch (RepositoryException e) {

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java?rev=1556488&r1=1556487&r2=1556488&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionStats.java
 Wed Jan  8 10:39:42 2014
@@ -52,12 +52,14 @@ public class SessionStats implements Ses
     private final AtomicReference<RepositoryException> lastFailedSave =
             new AtomicReference<RepositoryException>();
 
-    private final SessionDelegate sessionDelegate;
+    private final String sessionId;
+    private final AuthInfo authInfo;
 
     private Map<String, Object> attributes = Collections.emptyMap();
 
     public SessionStats(SessionDelegate sessionDelegate) {
-        this.sessionDelegate = sessionDelegate;
+        this.sessionId = sessionDelegate.toString();
+        this.authInfo = sessionDelegate.getAuthInfo();
     }
 
     public void setAttributes(Map<String, Object> attributes) {
@@ -94,7 +96,7 @@ public class SessionStats implements Ses
 
     @Override
     public String toString() {
-        return getAuthInfo().getUserID() + '@' + sessionDelegate.toString() + 
'@' + getLoginTimeStamp();
+        return getAuthInfo().getUserID() + '@' + sessionId + '@' + 
getLoginTimeStamp();
     }
 
     //------------------------------------------------------------< 
SessionMBean >---
@@ -106,7 +108,7 @@ public class SessionStats implements Ses
 
     @Override
     public AuthInfo getAuthInfo() {
-        return sessionDelegate.getAuthInfo();
+        return authInfo;
     }
 
     @Override

Modified: 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java?rev=1556488&r1=1556487&r2=1556488&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java
 Wed Jan  8 10:39:42 2014
@@ -25,6 +25,7 @@ import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.security.Privilege;
 
+import org.apache.jackrabbit.api.JackrabbitRepository;
 import 
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -72,6 +73,9 @@ public abstract class AbstractRepository
             adminSession = null;
         }
         // release repository field
+        if (repository instanceof JackrabbitRepository) {
+            ((JackrabbitRepository) repository).shutdown();
+        }
         repository = null;
         if (nodeStore != null) {
             fixture.dispose(nodeStore);


Reply via email to