You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2006/09/17 23:26:56 UTC

svn commit: r447148 - /jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java

Author: jukka
Date: Sun Sep 17 14:26:55 2006
New Revision: 447148

URL: http://svn.apache.org/viewvc?view=rev&rev=447148
Log:
JCR-446: Use a read-write lock to prevent logins during shutdown (and vice versa)

Modified:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&rev=447148&r1=447147&r2=447148
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Sun Sep 17 14:26:55 2006
@@ -19,6 +19,8 @@
 import EDU.oswego.cs.dl.util.concurrent.Mutex;
 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
 import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
+
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.api.JackrabbitRepository;
 import org.apache.jackrabbit.core.config.FileSystemConfig;
@@ -182,6 +184,17 @@
     private FileLock repLock;
 
     /**
+     * Shutdown lock for guaranteeing that no new sessions are started during
+     * repository shutdown and that a repository shutdown is not initiated
+     * during a login. Each session login acquires a read lock while the
+     * repository shutdown requires a write lock. This guarantees that there
+     * can be multiple concurrent logins when the repository is not shutting
+     * down, but that only a single shutdown and no concurrent logins can
+     * happen simultaneously.
+     */
+    private final ReadWriteLock shutdownLock = new WriterPreferenceReadWriteLock();
+
+    /**
      * private constructor
      *
      * @param repConfig
@@ -847,16 +860,34 @@
     }
 
     //-------------------------------------------------< JackrabbitRepository >
+
     /**
-     * Shuts down this repository.
+     * Shuts down this repository. The shutdown is guarded by a shutdown lock
+     * that prevents any new sessions from being started simultaneously.
      */
-    public synchronized void shutdown() {
-        // check status of this instance
-        if (disposed) {
-            // there's nothing to do here because the repository has already been shut down
-            return;
+    public void shutdown() {
+        try {
+            shutdownLock.writeLock().acquire();
+        } catch (InterruptedException e) {
+            // TODO: Should this be a checked exception?
+            throw new RuntimeException("Shutdown lock could not be acquired", e);
         }
 
+        try {
+            // check status of this instance
+            if (!disposed) {
+                doShutdown();
+            }
+        } finally {
+            shutdownLock.writeLock().release();
+        }
+    }
+
+    /**
+     * Private method that performs the actual shutdown after the shutdown
+     * lock has been acquired by the {@link #shutdown()} method.
+     */
+    private synchronized void doShutdown() {
         log.info("Shutting down repository...");
 
         // close active user sessions
@@ -1071,18 +1102,24 @@
      */
     public Session login(Credentials credentials, String workspaceName)
             throws LoginException, NoSuchWorkspaceException, RepositoryException {
-        // check sanity of this instance
-        sanityCheck();
-
-        if (workspaceName == null) {
-            workspaceName = repConfig.getDefaultWorkspaceName();
+        try {
+            shutdownLock.readLock().acquire();
+        } catch (InterruptedException e) {
+            throw new RepositoryException("Login lock could not be acquired", e);
         }
 
-        // check if workspace exists (will throw NoSuchWorkspaceException if not)
-        getWorkspaceInfo(workspaceName);
+        try {
+            // check sanity of this instance
+            sanityCheck();
 
-        if (credentials == null) {
-            try {
+            if (workspaceName == null) {
+                workspaceName = repConfig.getDefaultWorkspaceName();
+            }
+
+            // check if workspace exists (will throw NoSuchWorkspaceException if not)
+            getWorkspaceInfo(workspaceName);
+
+            if (credentials == null) {
                 // null credentials, obtain the identity of the already-authenticated
                 // subject from access control context
                 AccessControlContext acc = AccessController.getContext();
@@ -1090,18 +1127,9 @@
                 if (subject != null) {
                     return createSession(subject, workspaceName);
                 }
-            } catch (SecurityException se) {
-                throw new LoginException(
-                        "Unable to access authentication information", se);
-            } catch (AccessDeniedException ade) {
-                // authenticated subject is not authorized for the specified workspace
-                throw new LoginException("Workspace access denied", ade);
             }
-        }
-
-        // login either using JAAS or our own LoginModule
-        AuthContext authCtx;
-        try {
+            // login either using JAAS or our own LoginModule
+            AuthContext authCtx;
             LoginModuleConfig lmc = repConfig.getLoginModuleConfig();
             if (lmc == null) {
                 authCtx = new AuthContext.JAAS(repConfig.getAppName(), credentials);
@@ -1110,16 +1138,19 @@
                         lmc.getLoginModule(), lmc.getParameters(), credentials);
             }
             authCtx.login();
-        } catch (javax.security.auth.login.LoginException le) {
-            throw new LoginException(le.getMessage(), le);
-        }
 
-        // create session
-        try {
+            // create session
             return createSession(authCtx, workspaceName);
+        } catch (SecurityException se) {
+            throw new LoginException(
+                    "Unable to access authentication information", se);
+        } catch (javax.security.auth.login.LoginException le) {
+            throw new LoginException(le.getMessage(), le);
         } catch (AccessDeniedException ade) {
             // authenticated subject is not authorized for the specified workspace
-            throw new LoginException(ade.getMessage());
+            throw new LoginException("Workspace access denied", ade);
+        } finally {
+            shutdownLock.readLock().release();
         }
     }