diff --git a/docs/releasenotes.html b/docs/releasenotes.html index 08cb0cde064..63a341aa213 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -300,11 +300,11 @@

Migrating Client Code

Watch Management

In previous releases of ZooKeeper any watches registered by clients were lost if the client lost a connection to a ZooKeeper server. -This meant that developers had to track watches they were interested in and reregister them if a session disconnect event was recieved. +This meant that developers had to track watches they were interested in and reregister them if a session disconnect event was received. In this release the client library tracks watches that a client has registered and reregisters the watches when a connection is made to a new server. Applications that still manually reregister interest should continue working properly as long as they are able to handle unsolicited watches. For example, an old application may register a watch for /foo and /goo, lose the connection, and reregister only /goo. -As long as the application is able to recieve a notification for /foo, (probably ignoring it) it does not need to be changed. +As long as the application is able to receive a notification for /foo, (probably ignoring it) it does not need to be changed. One caveat to the watch management: it is possible to miss an event for the creation and deletion of a znode if watching for creation and both the create and delete happens while the client is disconnected from ZooKeeper.

diff --git a/src/c/acinclude.m4 b/src/c/acinclude.m4 index d0041d8c26a..a4d405a8044 100644 --- a/src/c/acinclude.m4 +++ b/src/c/acinclude.m4 @@ -7,7 +7,7 @@ # aminclude.m4 file and a compatible doxygen configuration file. Defines the # following public macros: # -# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. +# DX_???_FEATURE(ON|OFF) - control the default setting of a Doxygen feature. # Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, # 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' # for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF', diff --git a/src/c/src/zookeeper.c b/src/c/src/zookeeper.c index 7d82bf5c1c2..d38e17294e6 100644 --- a/src/c/src/zookeeper.c +++ b/src/c/src/zookeeper.c @@ -253,8 +253,6 @@ static void cleanup_bufs(zhandle_t *zh,int callCompletion,int rc); static int disable_conn_permute=0; // permute enabled by default static struct sockaddr_storage *addr_rw_server = 0; -static __attribute__((unused)) void print_completion_queue(zhandle_t *zh); - static void *SYNCHRONOUS_MARKER = (void*)&SYNCHRONOUS_MARKER; static int isValidPath(const char* path, const int flags); @@ -2530,26 +2528,6 @@ int api_epilog(zhandle_t *zh,int rc) return rc; } -static __attribute__((unused)) void print_completion_queue(zhandle_t *zh) -{ - completion_list_t* cptr; - - if(logLevelsent_requests.head==0) { - fprintf(LOGSTREAM,"empty\n"); - return; - } - - cptr=zh->sent_requests.head; - while(cptr){ - fprintf(LOGSTREAM,"%d,",cptr->xid); - cptr=cptr->next; - } - fprintf(LOGSTREAM,"end\n"); -} - //#ifdef THREADED // IO thread queues session events to be processed by the completion thread static int queue_session_event(zhandle_t *zh, int state) @@ -4357,7 +4335,7 @@ int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert, static const char* format_endpoint_info(const struct sockaddr_storage* ep) { static char buf[128] = { 0 }; - char addrstr[128] = { 0 }; + char addrstr[INET6_ADDRSTRLEN] = { 0 }; void *inaddr; #ifdef _WIN32 char * addrstring; diff --git a/src/java/main/org/apache/jute/OutputArchive.java b/src/java/main/org/apache/jute/OutputArchive.java index f53b1239107..5f78ea9dbc6 100644 --- a/src/java/main/org/apache/jute/OutputArchive.java +++ b/src/java/main/org/apache/jute/OutputArchive.java @@ -23,7 +23,7 @@ import java.util.TreeMap; /** - * Interface that alll the serializers have to implement. + * Interface that all the serializers have to implement. * */ public interface OutputArchive { diff --git a/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java b/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java index 0e5316d4eed..c2357cbba12 100644 --- a/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java +++ b/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java @@ -118,7 +118,7 @@ void updateLastSendAndHeard() { protected void readLength() throws IOException { int len = incomingBuffer.getInt(); if (len < 0 || len >= packetLen) { - throw new IOException("Packet len" + len + " is out of range!"); + throw new IOException("Packet len " + len + " is out of range!"); } incomingBuffer = ByteBuffer.allocate(len); } diff --git a/src/java/main/org/apache/zookeeper/cli/DelQuotaCommand.java b/src/java/main/org/apache/zookeeper/cli/DelQuotaCommand.java index 80054067516..c5ed4034d2b 100644 --- a/src/java/main/org/apache/zookeeper/cli/DelQuotaCommand.java +++ b/src/java/main/org/apache/zookeeper/cli/DelQuotaCommand.java @@ -63,7 +63,7 @@ public CliCommand parse(String[] cmdArgs) throws CliParseException { @Override public boolean exec() throws CliException { //if neither option -n or -b is specified, we delete - // the quota node for thsi node. + // the quota node for this node. String path = args[1]; try { if (cl.hasOption("b")) { diff --git a/src/java/main/org/apache/zookeeper/server/DataTree.java b/src/java/main/org/apache/zookeeper/server/DataTree.java index d5e5fa99526..eb4b7d65f2b 100644 --- a/src/java/main/org/apache/zookeeper/server/DataTree.java +++ b/src/java/main/org/apache/zookeeper/server/DataTree.java @@ -120,7 +120,7 @@ public class DataTree { .substring(procZookeeper.length() + 1); /** - * the path trie that keeps track fo the quota nodes in this datatree + * the path trie that keeps track of the quota nodes in this datatree */ private final PathTrie pTrie = new PathTrie(); diff --git a/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java b/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java index 2f60f781347..696c5e5ffe2 100644 --- a/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java +++ b/src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java @@ -170,6 +170,9 @@ public void processRequest(Request request) { } KeeperException ke = request.getException(); + if (ke instanceof SessionMovedException) { + throw ke; + } if (ke != null && request.type != OpCode.multi) { throw ke; } @@ -228,6 +231,9 @@ public void processRequest(Request request) { break; case OpCode.error: subResult = new ErrorResult(subTxnResult.err) ; + if (subTxnResult.err == Code.SESSIONMOVED.intValue()) { + throw new SessionMovedException(); + } break; default: throw new IOException("Invalid type of op"); diff --git a/src/java/systest/org/apache/zookeeper/test/system/QuorumPeerInstance.java b/src/java/systest/org/apache/zookeeper/test/system/QuorumPeerInstance.java index 2591a24265f..fdeb2b9441e 100644 --- a/src/java/systest/org/apache/zookeeper/test/system/QuorumPeerInstance.java +++ b/src/java/systest/org/apache/zookeeper/test/system/QuorumPeerInstance.java @@ -275,7 +275,7 @@ public static void startInstance(InstanceManager im, String quorumHostPort, int /** * Stop an instance of the quorumPeer * @param im the manager of the instance - * @param index the zero based index fo the server to stop + * @param index the zero based index of the server to stop * @throws InterruptedException * @throws KeeperException * @throws NoAssignmentException diff --git a/src/java/test/org/apache/zookeeper/test/LoadFromLogTest.java b/src/java/test/org/apache/zookeeper/test/LoadFromLogTest.java index 90de7557163..8303e55f7ee 100644 --- a/src/java/test/org/apache/zookeeper/test/LoadFromLogTest.java +++ b/src/java/test/org/apache/zookeeper/test/LoadFromLogTest.java @@ -91,7 +91,7 @@ public void testLoad() throws Exception { hdr = itr.getHeader(); expectedZxid++; Assert.assertTrue("not the same transaction. lastZxid=" + lastZxid + ", zxid=" + hdr.getZxid(), lastZxid != hdr.getZxid()); - Assert.assertTrue("excepting next transaction. expected=" + expectedZxid + ", retreived=" + hdr.getZxid(), (hdr.getZxid() == expectedZxid)); + Assert.assertTrue("excepting next transaction. expected=" + expectedZxid + ", retrieved=" + hdr.getZxid(), (hdr.getZxid() == expectedZxid)); lastZxid = hdr.getZxid(); }while(itr.next()); diff --git a/src/java/test/org/apache/zookeeper/test/MultiTransactionTest.java b/src/java/test/org/apache/zookeeper/test/MultiTransactionTest.java index fb864f59f10..a95fc503211 100644 --- a/src/java/test/org/apache/zookeeper/test/MultiTransactionTest.java +++ b/src/java/test/org/apache/zookeeper/test/MultiTransactionTest.java @@ -143,10 +143,10 @@ public void processResult(int rc, String path, Object ctx, } for (int i = 0; i < res.results.size(); i++) { OpResult opResult = res.results.get(i); - Assert.assertTrue("Did't recieve proper error response", + Assert.assertTrue("Did't receive proper error response", opResult instanceof ErrorResult); ErrorResult errRes = (ErrorResult) opResult; - Assert.assertEquals("Did't recieve proper error code", + Assert.assertEquals("Did't receive proper error code", expectedResultCodes.get(i).intValue(), errRes.getErr()); } } else { diff --git a/src/java/test/org/apache/zookeeper/test/QuorumTest.java b/src/java/test/org/apache/zookeeper/test/QuorumTest.java index cd1d1532b63..20388d8902e 100644 --- a/src/java/test/org/apache/zookeeper/test/QuorumTest.java +++ b/src/java/test/org/apache/zookeeper/test/QuorumTest.java @@ -245,6 +245,52 @@ public void process(WatchedEvent event) { } } + /** + * Make sure the previous connection closed after session move within + * multiop. + * + * @throws IOException + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void testSessionMovedWithMultiOp() throws Exception { + String hostPorts[] = qb.hostPort.split(","); + DisconnectableZooKeeper zk = new DisconnectableZooKeeper(hostPorts[0], + ClientBase.CONNECTION_TIMEOUT, new Watcher() { + public void process(WatchedEvent event) { + }}); + zk.multi(Arrays.asList( + Op.create("/testSessionMovedWithMultiOp", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL) + )); + + // session moved to the next server + ZooKeeper zknew = new ZooKeeper(hostPorts[1], + ClientBase.CONNECTION_TIMEOUT, + new Watcher() {public void process(WatchedEvent event) { + }}, + zk.getSessionId(), + zk.getSessionPasswd()); + zknew.multi(Arrays.asList( + Op.create("/testSessionMovedWithMultiOp-1", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL) + )); + + // try to issue the multi op again from the old connection + // expect to have ConnectionLossException instead of keep + // getting SessionMovedException + try { + zk.multi(Arrays.asList( + Op.create("/testSessionMovedWithMultiOp-Failed", + new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL) + )); + Assert.fail("Should have lost the connection"); + } catch (KeeperException.ConnectionLossException e) { + } + + zk.close(); + zknew.close(); + } + /** * Connect to two different servers with two different handles using the same session and * make sure we cannot do any changes. @@ -295,8 +341,8 @@ ClientBase.CONNECTION_TIMEOUT, new DiscoWatcher(), zk.close(); } - /** - * See ZOOKEEPER-790 for details + /** + * See ZOOKEEPER-790 for details * */ @Test public void testFollowersStartAfterLeader() throws Exception { @@ -310,10 +356,10 @@ public void testFollowersStartAfterLeader() throws Exception { // break the quorum qu.shutdown(index); - + // try to reestablish the quorum qu.start(index); - + // Connect the client after services are restarted (otherwise we would get // SessionExpiredException as the previous local session was not persisted). ZooKeeper zk = new ZooKeeper( @@ -321,7 +367,7 @@ public void testFollowersStartAfterLeader() throws Exception { ClientBase.CONNECTION_TIMEOUT, watcher); try{ - watcher.waitForConnected(CONNECTION_TIMEOUT); + watcher.waitForConnected(CONNECTION_TIMEOUT); } catch(TimeoutException e) { Assert.fail("client could not connect to reestablished quorum: giving up after 30+ seconds."); } @@ -334,7 +380,7 @@ public void testFollowersStartAfterLeader() throws Exception { /** * Tests if a multiop submitted to a non-leader propagates to the leader properly * (see ZOOKEEPER-1124). - * + * * The test works as follows. It has a client connect to a follower and submit a multiop * to the follower. It then verifies that the multiop successfully gets committed by the leader. * diff --git a/src/recipes/lock/src/c/acinclude.m4 b/src/recipes/lock/src/c/acinclude.m4 index d0041d8c26a..a4d405a8044 100644 --- a/src/recipes/lock/src/c/acinclude.m4 +++ b/src/recipes/lock/src/c/acinclude.m4 @@ -7,7 +7,7 @@ # aminclude.m4 file and a compatible doxygen configuration file. Defines the # following public macros: # -# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. +# DX_???_FEATURE(ON|OFF) - control the default setting of a Doxygen feature. # Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, # 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' # for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF', diff --git a/src/recipes/queue/src/c/acinclude.m4 b/src/recipes/queue/src/c/acinclude.m4 index d0041d8c26a..a4d405a8044 100644 --- a/src/recipes/queue/src/c/acinclude.m4 +++ b/src/recipes/queue/src/c/acinclude.m4 @@ -7,7 +7,7 @@ # aminclude.m4 file and a compatible doxygen configuration file. Defines the # following public macros: # -# DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. +# DX_???_FEATURE(ON|OFF) - control the default setting of a Doxygen feature. # Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, # 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' # for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF',