You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ma...@apache.org on 2012/09/17 09:56:20 UTC
svn commit: r1386497 - in /zookeeper/branches/branch-3.4: CHANGES.txt
src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java
src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java
Author: mahadev
Date: Mon Sep 17 07:56:19 2012
New Revision: 1386497
URL: http://svn.apache.org/viewvc?rev=1386497&view=rev
Log:
ZOOKEEPER-1496. Ephemeral node not getting cleared even after client has exited (Rakesh R via mahadev)
Added:
zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java
Modified:
zookeeper/branches/branch-3.4/CHANGES.txt
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java
Modified: zookeeper/branches/branch-3.4/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/CHANGES.txt?rev=1386497&r1=1386496&r2=1386497&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/CHANGES.txt (original)
+++ zookeeper/branches/branch-3.4/CHANGES.txt Mon Sep 17 07:56:19 2012
@@ -111,6 +111,9 @@ BUGFIXES:
ZOOKEEPER-1483. Fix leader election recipe documentation. (Michi Mutsuzaki
via mahadev)
+ ZOOKEEPER-1496. Ephemeral node not getting cleared even after client has
+ exited (Rakesh R via mahadev)
+
IMPROVEMENTS:
ZOOKEEPER-1389. it would be nice if start-foreground used exec $JAVA
Modified: zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java?rev=1386497&r1=1386496&r2=1386497&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java (original)
+++ zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/SessionTrackerImpl.java Mon Sep 17 07:56:19 2012
@@ -150,7 +150,7 @@ public class SessionTrackerImpl extends
set = sessionSets.remove(nextExpirationTime);
if (set != null) {
for (SessionImpl s : set.sessions) {
- sessionsById.remove(s.sessionId);
+ setSessionClosing(s.sessionId);
expirer.expire(s);
}
}
@@ -170,7 +170,8 @@ public class SessionTrackerImpl extends
+ Long.toHexString(sessionId) + " with timeout " + timeout);
}
SessionImpl s = sessionsById.get(sessionId);
- if (s == null) {
+ // Return false, if the session doesn't exists or marked as closing
+ if (s == null || s.isClosing()) {
return false;
}
long expireTime = roundToInterval(System.currentTimeMillis() + timeout);
@@ -212,7 +213,11 @@ public class SessionTrackerImpl extends
+ Long.toHexString(sessionId));
}
if (s != null) {
- sessionSets.get(s.tickTime).sessions.remove(s);
+ SessionSet set = sessionSets.get(s.tickTime);
+ // Session expiration has been removing the sessions
+ if(set != null){
+ set.sessions.remove(s);
+ }
}
}
@@ -266,7 +271,7 @@ public class SessionTrackerImpl extends
synchronized public void setOwner(long id, Object owner) throws SessionExpiredException {
SessionImpl session = sessionsById.get(id);
- if (session == null) {
+ if (session == null || session.isClosing()) {
throw new KeeperException.SessionExpiredException();
}
session.owner = owner;
Added: zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java?rev=1386497&view=auto
==============================================================================
--- zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java (added)
+++ zookeeper/branches/branch-3.4/src/java/test/org/apache/zookeeper/server/SessionTrackerTest.java Mon Sep 17 07:56:19 2012
@@ -0,0 +1,156 @@
+/**
+ * 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
+ *
+ * http://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.zookeeper.server;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.server.SessionTrackerImpl.SessionImpl;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Test;
+
+/**
+ * Testing zk client session logic in sessiontracker
+ */
+public class SessionTrackerTest extends ZKTestCase {
+
+ private final long sessionId = 339900;
+ private final int sessionTimeout = 3000;
+ private FirstProcessor firstProcessor;
+ private CountDownLatch latch;
+
+ /**
+ * Verify the create session call in the Leader.FinalRequestProcessor after
+ * the session expiration.
+ */
+ @Test(timeout = 20000)
+ public void testAddSessionAfterSessionExpiry() throws Exception {
+ ZooKeeperServer zks = setupSessionTracker();
+
+ latch = new CountDownLatch(1);
+ zks.sessionTracker.addSession(sessionId, sessionTimeout);
+ SessionTrackerImpl sessionTrackerImpl = (SessionTrackerImpl) zks.sessionTracker;
+ SessionImpl sessionImpl = sessionTrackerImpl.sessionsById
+ .get(sessionId);
+ Assert.assertNotNull("Sessionid:" + sessionId
+ + " doesn't exists in sessiontracker", sessionImpl);
+
+ // verify the session existence
+ Object sessionOwner = new Object();
+ sessionTrackerImpl.checkSession(sessionId, sessionOwner);
+
+ // waiting for the session expiry
+ latch.await(sessionTimeout * 2, TimeUnit.MILLISECONDS);
+
+ // Simulating FinalRequestProcessor logic: create session request has
+ // delayed and now reaches FinalRequestProcessor. Here the leader zk
+ // will do sessionTracker.addSession(id, timeout)
+ sessionTrackerImpl.addSession(sessionId, sessionTimeout);
+ try {
+ sessionTrackerImpl.checkSession(sessionId, sessionOwner);
+ Assert.fail("Should throw session expiry exception "
+ + "as the session has expired and closed");
+ } catch (KeeperException.SessionExpiredException e) {
+ // expected behaviour
+ }
+ Assert.assertTrue("Session didn't expired", sessionImpl.isClosing());
+ Assert.assertFalse("Session didn't expired", sessionTrackerImpl
+ .touchSession(sessionId, sessionTimeout));
+ Assert.assertEquals(
+ "Duplicate session expiry request has been generated", 1,
+ firstProcessor.getCountOfCloseSessionReq());
+ }
+
+ /**
+ * Verify the session closure request has reached PrepRequestProcessor soon
+ * after session expiration by the session tracker
+ */
+ @Test(timeout = 20000)
+ public void testCloseSessionRequestAfterSessionExpiry() throws Exception {
+ ZooKeeperServer zks = setupSessionTracker();
+
+ latch = new CountDownLatch(1);
+ zks.sessionTracker.addSession(sessionId, sessionTimeout);
+ SessionTrackerImpl sessionTrackerImpl = (SessionTrackerImpl) zks.sessionTracker;
+ SessionImpl sessionImpl = sessionTrackerImpl.sessionsById
+ .get(sessionId);
+ Assert.assertNotNull("Sessionid:" + sessionId
+ + " doesn't exists in sessiontracker", sessionImpl);
+
+ // verify the session existence
+ Object sessionOwner = new Object();
+ sessionTrackerImpl.checkSession(sessionId, sessionOwner);
+
+ // waiting for the session expiry
+ latch.await(sessionTimeout * 2, TimeUnit.MILLISECONDS);
+
+ // Simulating close session request: removeSession() will be executed
+ // while OpCode.closeSession
+ sessionTrackerImpl.removeSession(sessionId);
+ SessionImpl actualSession = sessionTrackerImpl.sessionsById
+ .get(sessionId);
+ Assert.assertNull("Session:" + sessionId
+ + " still exists after removal", actualSession);
+ }
+
+ private ZooKeeperServer setupSessionTracker() throws IOException {
+ File tmpDir = ClientBase.createTmpDir();
+ ClientBase.setupTestEnv();
+ ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
+ zks.setupRequestProcessors();
+ firstProcessor = new FirstProcessor(zks, null);
+ zks.firstProcessor = firstProcessor;
+
+ // setup session tracker
+ zks.createSessionTracker();
+ zks.startSessionTracker();
+ return zks;
+ }
+
+ // Mock processor used in zookeeper server
+ private class FirstProcessor extends PrepRequestProcessor {
+ private volatile int countOfCloseSessionReq = 0;
+
+ public FirstProcessor(ZooKeeperServer zks,
+ RequestProcessor nextProcessor) {
+ super(zks, nextProcessor);
+ }
+
+ @Override
+ public void processRequest(Request request) {
+ // check session close request
+ if (request.type == OpCode.closeSession) {
+ latch.countDown();
+ countOfCloseSessionReq++;
+ }
+ }
+
+ // return number of session expiry calls
+ int getCountOfCloseSessionReq() {
+ return countOfCloseSessionReq;
+ }
+ }
+}