Author: mahadev Date: Thu Apr 9 21:02:49 2009 New Revision: 763799 URL: http://svn.apache.org/viewvc?rev=763799&view=rev Log: ZOOKEEPER-355. make validatePath non public in Zookeeper client api. (phunt via mahadev)
Modified: hadoop/zookeeper/trunk/CHANGES.txt hadoop/zookeeper/trunk/src/c/src/zookeeper.c hadoop/zookeeper/trunk/src/c/tests/TestClient.cc hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ClientTest.java Modified: hadoop/zookeeper/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/CHANGES.txt (original) +++ hadoop/zookeeper/trunk/CHANGES.txt Thu Apr 9 21:02:49 2009 @@ -45,6 +45,9 @@ ZOOKEEPER-347. zkfuse uses non-standard String. (patrick hunt via mahadev) + ZOOKEEPER-355. make validatePath non public in Zookeeper client api. (phunt +via mahadev) + IMPROVEMENTS: ZOOKEEPER-308. improve the atomic broadcast performance 3x. (breed via mahadev) Modified: hadoop/zookeeper/trunk/src/c/src/zookeeper.c URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/src/zookeeper.c?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/src/c/src/zookeeper.c (original) +++ hadoop/zookeeper/trunk/src/c/src/zookeeper.c Thu Apr 9 21:02:49 2009 @@ -1902,7 +1902,7 @@ return rc; } -static int isValidPath(const char* path) { +static int isValidPath(const char* path, const int flags) { if (path == 0) return 0; const int len = strlen(path); @@ -1912,7 +1912,7 @@ return 0; if (len == 1) // done checking - it's the root return 1; - if (path[len - 1] == '/') + if (path[len - 1] == '/' && !(flags & ZOO_SEQUENCE)) return 0; char lastc = '/'; @@ -1926,11 +1926,13 @@ } else if (c == '/' && lastc == '/') { return 0; } else if (c == '.' && lastc == '.') { - if (path[i-2] == '/' && ((i + 1 == len) || path[i+1] == '/')) { + if (path[i-2] == '/' && (((i + 1 == len) && !(flags & ZOO_SEQUENCE)) + || path[i+1] == '/')) { return 0; } } else if (c == '.') { - if ((path[i-1] == '/') && ((i + 1 == len) || path[i+1] == '/')) { + if ((path[i-1] == '/') && (((i + 1 == len) && !(flags & ZOO_SEQUENCE)) + || path[i+1] == '/')) { return 0; } } else if (c > 0x00 && c < 0x1f) { @@ -1956,7 +1958,7 @@ struct GetDataRequest req = { (char*)path, watcher!=0 }; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -1988,7 +1990,7 @@ struct SetDataRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2015,7 +2017,7 @@ } int zoo_acreate(zhandle_t *zh, const char *path, const char *value, - int valuelen, const struct ACL_vector *acl_entries, int ephemeral, + int valuelen, const struct ACL_vector *acl_entries, int flags, string_completion_t completion, const void *data) { struct oarchive *oa; @@ -2023,13 +2025,13 @@ struct CreateRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, flags)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; oa = create_buffer_oarchive(); req.path = (char*)path; - req.flags = ephemeral; + req.flags = flags; req.data.buff = (char*)value; req.data.len = valuelen; if (acl_entries == 0) { @@ -2063,7 +2065,7 @@ struct DeleteRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2102,7 +2104,7 @@ struct ExistsRequest req = {(char*)path, watcher!=0 }; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2141,7 +2143,7 @@ struct GetChildrenRequest req={(char*)path, watcher!=0 }; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2172,7 +2174,7 @@ struct SyncRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2204,7 +2206,7 @@ struct GetACLRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; @@ -2235,7 +2237,7 @@ struct SetACLRequest req; int rc; - if (zh==0 || !isValidPath(path)) + if (zh==0 || !isValidPath(path, 0)) return ZBADARGUMENTS; if (is_unrecoverable(zh)) return ZINVALIDSTATE; Modified: hadoop/zookeeper/trunk/src/c/tests/TestClient.cc URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/c/tests/TestClient.cc?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/src/c/tests/TestClient.cc (original) +++ hadoop/zookeeper/trunk/src/c/tests/TestClient.cc Thu Apr 9 21:02:49 2009 @@ -296,6 +296,16 @@ path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0)); } + static void verifyCreateFailsSeq(const char *path, zhandle_t *zk) { + CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk, + path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0)); + } + + static void verifyCreateOkSeq(const char *path, zhandle_t *zk) { + CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk, + path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0)); + } + /** returns false if the vectors dont match @@ -370,6 +380,16 @@ verifyCreateFails("foo", zk); verifyCreateFails("a", zk); + // verify that trailing fails, except for seq which adds suffix + verifyCreateOk("/createseq", zk); + verifyCreateFails("/createseq/", zk); + verifyCreateOkSeq("/createseq/", zk); + verifyCreateOkSeq("/createseq/.", zk); + verifyCreateOkSeq("/createseq/..", zk); + verifyCreateFailsSeq("/createseq//", zk); + verifyCreateFailsSeq("/createseq/./", zk); + verifyCreateFailsSeq("/createseq/../", zk); + verifyCreateOk("/.foo", zk); verifyCreateOk("/.f.", zk); verifyCreateOk("/..f", zk); Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java (original) +++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/ZooKeeper.java Thu Apr 9 21:02:49 2009 @@ -33,6 +33,7 @@ import org.apache.zookeeper.AsyncCallback.StatCallback; import org.apache.zookeeper.AsyncCallback.StringCallback; import org.apache.zookeeper.AsyncCallback.VoidCallback; +import org.apache.zookeeper.common.PathUtils; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.proto.CreateRequest; @@ -127,7 +128,7 @@ * the public methods will not be exposed as part of the ZooKeeper client * API. */ - private class ZKWatchManager implements ClientWatchManager { + private static class ZKWatchManager implements ClientWatchManager { private final Map<String, Set<Watcher>> dataWatches = new HashMap<String, Set<Watcher>>(); private final Map<String, Set<Watcher>> existWatches = @@ -500,7 +501,8 @@ CreateMode createMode) throws KeeperException, InterruptedException { - validatePath(path); + // also handle the case where server will append name suffix + PathUtils.validatePath(path, createMode.isSequential()); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.create); @@ -522,72 +524,6 @@ } /** - * Validate the provided znode path string - * @param path znode path string - * @throws IllegalArgumentException if the path is invalid - */ - public static void validatePath(String path) throws IllegalArgumentException { - if (path == null) { - throw new IllegalArgumentException("Path cannot be null"); - } - if (path.length() == 0) { - throw new IllegalArgumentException("Path length must be > 0"); - } - if (path.charAt(0) != '/') { - throw new IllegalArgumentException( - "Path must start with / character"); - } - if (path.length() == 1) { // done checking - it's the root - return; - } - if (path.charAt(path.length() - 1) == '/') { - throw new IllegalArgumentException( - "Path must not end with / character"); - } - - String reason = null; - char lastc = '/'; - char chars[] = path.toCharArray(); - char c; - for (int i = 1; i < chars.length; lastc = chars[i], i++) { - c = chars[i]; - - if (c == 0) { - reason = "null character not allowed @" + i; - break; - } else if (c == '/' && lastc == '/') { - reason = "empty node name specified @" + i; - break; - } else if (c == '.' && lastc == '.') { - if (chars[i-2] == '/' && - ((i + 1 == chars.length) - || chars[i+1] == '/')) { - reason = "relative paths not allowed @" + i; - break; - } - } else if (c == '.') { - if (chars[i-1] == '/' && - ((i + 1 == chars.length) - || chars[i+1] == '/')) { - reason = "relative paths not allowed @" + i; - break; - } - } else if (c > '\u0000' && c < '\u001f' - || c > '\u007f' && c < '\u009F' - || c > '\ud800' && c < '\uf8ff' - || c > '\ufff0' && c < '\uffff') { - reason = "invalid charater @" + i; - break; - } - } - - if (reason != null) { - throw new IllegalArgumentException( - "Invalid path string \"" + path + "\" caused by " + reason); - } - } - - /** * The Asynchronous version of create. The request doesn't actually until * the asynchronous callback is called. * @@ -597,7 +533,8 @@ public void create(String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx) { - validatePath(path); + // also handle the case where server will append name suffix + PathUtils.validatePath(path, createMode.isSequential()); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.create); @@ -639,7 +576,7 @@ */ public void delete(String path, int version) throws InterruptedException, KeeperException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.delete); @@ -659,7 +596,7 @@ * @see #delete(String, int) */ public void delete(String path, int version, VoidCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.delete); @@ -689,7 +626,7 @@ public Stat exists(String path, Watcher watcher) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.exists); @@ -745,7 +682,7 @@ public void exists(String path, Watcher watcher, StatCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.exists); @@ -792,7 +729,7 @@ */ public byte[] getData(String path, Watcher watcher, Stat stat) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getData); @@ -844,7 +781,7 @@ * @see #getData(String, Watcher, Stat) */ public void getData(String path, Watcher watcher, DataCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getData); @@ -900,7 +837,7 @@ */ public Stat setData(String path, byte data[], int version) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setData); @@ -924,7 +861,7 @@ */ public void setData(String path, byte data[], int version, StatCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setData); @@ -955,7 +892,7 @@ */ public List<ACL> getACL(String path, Stat stat) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getACL); @@ -977,7 +914,7 @@ * @see #getACL(String, Stat) */ public void getACL(String path, Stat stat, ACLCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getACL); @@ -1011,7 +948,7 @@ */ public Stat setACL(String path, List<ACL> acl, int version) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setACL); @@ -1038,7 +975,7 @@ */ public void setACL(String path, List<ACL> acl, int version, StatCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setACL); @@ -1075,7 +1012,7 @@ */ public List<String> getChildren(String path, Watcher watcher) throws KeeperException, InterruptedException { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren); @@ -1127,7 +1064,7 @@ */ public void getChildren(String path, Watcher watcher, ChildrenCallback cb, Object ctx) { - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren); @@ -1162,7 +1099,7 @@ * @throws IllegalArgumentException if an invalid path is specified */ public void sync(String path, VoidCallback cb, Object ctx){ - validatePath(path); + PathUtils.validatePath(path); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.sync); Modified: hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java (original) +++ hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java Thu Apr 9 21:02:49 2009 @@ -30,9 +30,9 @@ import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; -import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.KeeperException.Code; import org.apache.zookeeper.ZooDefs.OpCode; +import org.apache.zookeeper.common.PathUtils; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Id; import org.apache.zookeeper.data.StatPersisted; @@ -205,13 +205,6 @@ Long.toHexString(request.sessionId)); throw new KeeperException.BadArgumentsException(); } - try { - ZooKeeper.validatePath(path); - } catch(IllegalArgumentException ie) { - LOG.warn("Invalid path " + path + " with session " + - Long.toHexString(request.sessionId)); - throw new KeeperException.BadArgumentsException(); - } if (!fixupACL(request.authInfo, createRequest.getAcl())) { throw new KeeperException.InvalidACLException(); } @@ -221,11 +214,19 @@ checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo); int parentCVersion = parentRecord.stat.getCversion(); - CreateMode createMode = CreateMode.fromFlag(createRequest.getFlags()); + CreateMode createMode = + CreateMode.fromFlag(createRequest.getFlags()); if (createMode.isSequential()) { path = path + String.format("%010d", parentCVersion); } try { + PathUtils.validatePath(path); + } catch(IllegalArgumentException ie) { + LOG.warn("Invalid path " + path + " with session " + + Long.toHexString(request.sessionId)); + throw new KeeperException.BadArgumentsException(); + } + try { if (getRecordForPath(path) != null) { throw new KeeperException.NodeExistsException(); } Modified: hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ClientTest.java URL: http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ClientTest.java?rev=763799&r1=763798&r2=763799&view=diff ============================================================================== --- hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ClientTest.java (original) +++ hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/ClientTest.java Thu Apr 9 21:02:49 2009 @@ -487,6 +487,49 @@ verifyCreateFails("foo", zk); verifyCreateFails("a", zk); + + zk.create("/createseqpar", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + // next two steps - related to sequential processing + // 1) verify that empty child name fails if not sequential + try { + zk.create("/createseqpar/", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + assertTrue(false); + } catch(IllegalArgumentException be) { + // catch this. + } + + // 2) verify that empty child name success if sequential + zk.create("/createseqpar/", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + zk.create("/createseqpar/.", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + zk.create("/createseqpar/..", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + try { + zk.create("/createseqpar//", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + assertTrue(false); + } catch(IllegalArgumentException be) { + // catch this. + } + try { + zk.create("/createseqpar/./", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + assertTrue(false); + } catch(IllegalArgumentException be) { + // catch this. + } + try { + zk.create("/createseqpar/../", null, Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT_SEQUENTIAL); + assertTrue(false); + } catch(IllegalArgumentException be) { + // catch this. + } + + //check for the code path that throws at server PrepRequestProcessor.failCreate = true; try {