Return-Path: X-Original-To: apmail-accumulo-commits-archive@www.apache.org Delivered-To: apmail-accumulo-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 98409108B7 for ; Fri, 13 Dec 2013 23:01:02 +0000 (UTC) Received: (qmail 7722 invoked by uid 500); 13 Dec 2013 23:01:02 -0000 Delivered-To: apmail-accumulo-commits-archive@accumulo.apache.org Received: (qmail 7624 invoked by uid 500); 13 Dec 2013 23:01:02 -0000 Mailing-List: contact commits-help@accumulo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@accumulo.apache.org Delivered-To: mailing list commits@accumulo.apache.org Received: (qmail 7465 invoked by uid 99); 13 Dec 2013 23:01:02 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Dec 2013 23:01:02 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 178C88B8961; Fri, 13 Dec 2013 23:01:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ctubbsii@apache.org To: commits@accumulo.apache.org Date: Fri, 13 Dec 2013 23:01:03 -0000 Message-Id: <72c87f1b09dc402781c7ce96da5d7adf@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/4] git commit: Merge branch '1.4.5-SNAPSHOT' into 1.5.1-SNAPSHOT Merge branch '1.4.5-SNAPSHOT' into 1.5.1-SNAPSHOT Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/c84acfc9 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/c84acfc9 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/c84acfc9 Branch: refs/heads/1.6.0-SNAPSHOT Commit: c84acfc9a6fbe4f86699ab60ea354d8f1fe942cc Parents: b65bdd6 335f693 Author: Christopher Tubbs Authored: Fri Dec 13 17:55:48 2013 -0500 Committer: Christopher Tubbs Committed: Fri Dec 13 17:55:48 2013 -0500 ---------------------------------------------------------------------- .../apache/accumulo/core/client/Instance.java | 30 +- .../apache/accumulo/core/data/RangeTest.java | 337 ++++++++++--------- .../accumulo/fate/zookeeper/ZooCache.java | 110 +++--- .../accumulo/fate/zookeeper/ZooReader.java | 39 ++- 4 files changed, 256 insertions(+), 260 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/c84acfc9/core/src/main/java/org/apache/accumulo/core/client/Instance.java ---------------------------------------------------------------------- diff --cc core/src/main/java/org/apache/accumulo/core/client/Instance.java index 6449765,0000000..c67220d mode 100644,000000..100644 --- a/core/src/main/java/org/apache/accumulo/core/client/Instance.java +++ b/core/src/main/java/org/apache/accumulo/core/client/Instance.java @@@ -1,174 -1,0 +1,172 @@@ +/* + * 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.accumulo.core.client; + - import java.io.Closeable; +import java.nio.ByteBuffer; +import java.util.List; + +import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; +import org.apache.accumulo.core.client.security.tokens.PasswordToken; +import org.apache.accumulo.core.conf.AccumuloConfiguration; + +/** + * This class represents the information a client needs to know to connect to an instance of accumulo. + * + */ - public interface Instance extends Closeable { ++public interface Instance { + /** + * Returns the location of the tablet server that is serving the root tablet. + * + * @return location in "hostname:port" form + */ + public abstract String getRootTabletLocation(); - ++ + /** + * Returns the location(s) of the accumulo master and any redundant servers. + * + * @return a list of locations in "hostname:port" form + */ + public abstract List getMasterLocations(); - ++ + /** + * Returns a unique string that identifies this instance of accumulo. + * + * @return a UUID + */ + public abstract String getInstanceID(); - ++ + /** + * Returns the instance name given at system initialization time. + * + * @return current instance name + */ + public abstract String getInstanceName(); - ++ + /** + * Returns a comma-separated list of zookeeper servers the instance is using. + * + * @return the zookeeper servers this instance is using in "hostname:port" form + */ + public abstract String getZooKeepers(); - ++ + /** + * Returns the zookeeper connection timeout. + * + * @return the configured timeout to connect to zookeeper + */ + public abstract int getZooKeepersSessionTimeOut(); - ++ + /** + * Returns a connection to accumulo. + * + * @param user + * a valid accumulo user + * @param pass + * A UTF-8 encoded password. The password may be cleared after making this call. + * @return the accumulo Connector + * @throws AccumuloException + * when a generic exception occurs + * @throws AccumuloSecurityException + * when a user's credentials are invalid + * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with {@link PasswordToken} + */ + @Deprecated + public abstract Connector getConnector(String user, byte[] pass) throws AccumuloException, AccumuloSecurityException; - ++ + /** + * Returns a connection to accumulo. + * + * @param auth + * An Credentials object. + * @return the accumulo Connector + * @throws AccumuloException + * when a generic exception occurs + * @throws AccumuloSecurityException + * when a user's credentials are invalid + * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with {@link PasswordToken} + */ + @Deprecated + public abstract Connector getConnector(org.apache.accumulo.core.security.thrift.AuthInfo auth) throws AccumuloException, AccumuloSecurityException; - ++ + /** + * Returns a connection to accumulo. + * + * @param user + * a valid accumulo user + * @param pass + * A UTF-8 encoded password. The password may be cleared after making this call. + * @return the accumulo Connector + * @throws AccumuloException + * when a generic exception occurs + * @throws AccumuloSecurityException + * when a user's credentials are invalid + * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with {@link PasswordToken} + */ + @Deprecated + public abstract Connector getConnector(String user, ByteBuffer pass) throws AccumuloException, AccumuloSecurityException; - ++ + /** + * Returns a connection to this instance of accumulo. + * + * @param user + * a valid accumulo user + * @param pass + * If a mutable CharSequence is passed in, it may be cleared after this call. + * @return the accumulo Connector + * @throws AccumuloException + * when a generic exception occurs + * @throws AccumuloSecurityException + * when a user's credentials are invalid + * @deprecated since 1.5, use {@link #getConnector(String, AuthenticationToken)} with {@link PasswordToken} + */ + @Deprecated + public abstract Connector getConnector(String user, CharSequence pass) throws AccumuloException, AccumuloSecurityException; + + /** + * Closes up the instance to free up all associated resources. You should try to reuse an Instance as much as you can because there is some location caching + * stored which will enhance performance. + */ - @Override + public abstract void close(); - ++ + /** + * Returns the AccumuloConfiguration to use when interacting with this instance. + * + * @return the AccumuloConfiguration that specifies properties related to interacting with this instance + */ + public abstract AccumuloConfiguration getConfiguration(); - ++ + /** + * Set the AccumuloConfiguration to use when interacting with this instance. + * + * @param conf + * accumulo configuration + */ + public abstract void setConfiguration(AccumuloConfiguration conf); - ++ + /** + * Returns a connection to this instance of accumulo. + * + * @param principal + * a valid accumulo user + * @param token + * Use the token type configured for the Accumulo instance you are connecting to. An Accumulo instance with default configurations will use + * {@link PasswordToken} + * @since 1.5.0 + */ + public abstract Connector getConnector(String principal, AuthenticationToken token) throws AccumuloException, AccumuloSecurityException; - ++ +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/c84acfc9/core/src/test/java/org/apache/accumulo/core/data/RangeTest.java ---------------------------------------------------------------------- diff --cc core/src/test/java/org/apache/accumulo/core/data/RangeTest.java index 68d9731,0000000..1f9a40d mode 100644,000000..100644 --- a/core/src/test/java/org/apache/accumulo/core/data/RangeTest.java +++ b/core/src/test/java/org/apache/accumulo/core/data/RangeTest.java @@@ -1,822 -1,0 +1,823 @@@ +/* + * 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.accumulo.core.data; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.InvalidObjectException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.accumulo.core.data.thrift.TRange; +import org.apache.hadoop.io.Text; + +public class RangeTest extends TestCase { + private Range nr(String k1, String k2) { + Key ik1 = null; + if (k1 != null) + ik1 = new Key(new Text(k1), 0l); - ++ + Key ik2 = null; + if (k2 != null) + ik2 = new Key(new Text(k2), 0l); - ++ + return new Range(ik1, ik2); + } - ++ + private List nrl(Range... ranges) { + return Arrays.asList(ranges); + } - ++ + private void check(List rl, List expected) { + HashSet s1 = new HashSet(rl); + HashSet s2 = new HashSet(expected); - ++ + assertTrue("got : " + rl + " expected : " + expected, s1.equals(s2)); + } - ++ + public void testMergeOverlapping1() { + List rl = nrl(nr("a", "c"), nr("a", "b")); + List expected = nrl(nr("a", "c")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping2() { + List rl = nrl(nr("a", "c"), nr("d", "f")); + List expected = nrl(nr("a", "c"), nr("d", "f")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping3() { + List rl = nrl(nr("a", "e"), nr("b", "f"), nr("c", "r"), nr("g", "j"), nr("t", "x")); + List expected = nrl(nr("a", "r"), nr("t", "x")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping4() { + List rl = nrl(nr("a", "e"), nr("b", "f"), nr("c", "r"), nr("g", "j")); + List expected = nrl(nr("a", "r")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping5() { + List rl = nrl(nr("a", "e")); + List expected = nrl(nr("a", "e")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping6() { + List rl = nrl(); + List expected = nrl(); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping7() { + List rl = nrl(nr("a", "e"), nr("g", "q"), nr("r", "z")); + List expected = nrl(nr("a", "e"), nr("g", "q"), nr("r", "z")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping8() { + List rl = nrl(nr("a", "c"), nr("a", "c")); + List expected = nrl(nr("a", "c")); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping9() { + List rl = nrl(nr(null, null)); + List expected = nrl(nr(null, null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping10() { + List rl = nrl(nr(null, null), nr("a", "c")); + List expected = nrl(nr(null, null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping11() { + List rl = nrl(nr("a", "c"), nr(null, null)); + List expected = nrl(nr(null, null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping12() { + List rl = nrl(nr("b", "d"), nr("c", null)); + List expected = nrl(nr("b", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping13() { + List rl = nrl(nr("b", "d"), nr("a", null)); + List expected = nrl(nr("a", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping14() { + List rl = nrl(nr("b", "d"), nr("e", null)); + List expected = nrl(nr("b", "d"), nr("e", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping15() { + List rl = nrl(nr("b", "d"), nr("e", null), nr("c", "f")); + List expected = nrl(nr("b", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping16() { + List rl = nrl(nr("b", "d"), nr("f", null), nr("c", "e")); + List expected = nrl(nr("b", "e"), nr("f", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping17() { + List rl = nrl(nr("b", "d"), nr("r", null), nr("c", "e"), nr("g", "t")); + List expected = nrl(nr("b", "e"), nr("g", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping18() { + List rl = nrl(nr(null, "d"), nr("r", null), nr("c", "e"), nr("g", "t")); + List expected = nrl(nr(null, "e"), nr("g", null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping19() { + List rl = nrl(nr(null, "d"), nr("r", null), nr("c", "e"), nr("g", "t"), nr("d", "h")); + List expected = nrl(nr(null, null)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping20() { - ++ + List rl = nrl(new Range(new Text("a"), true, new Text("b"), false), new Range(new Text("b"), false, new Text("c"), false)); + List expected = nrl(new Range(new Text("a"), true, new Text("b"), false), new Range(new Text("b"), false, new Text("c"), false)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Text("a"), true, new Text("b"), false), new Range(new Text("b"), true, new Text("c"), false)); + expected = nrl(new Range(new Text("a"), true, new Text("c"), false)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Text("a"), true, new Text("b"), true), new Range(new Text("b"), false, new Text("c"), false)); + expected = nrl(new Range(new Text("a"), true, new Text("c"), false)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Text("a"), true, new Text("b"), true), new Range(new Text("b"), true, new Text("c"), false)); + expected = nrl(new Range(new Text("a"), true, new Text("c"), false)); + check(Range.mergeOverlapping(rl), expected); - ++ + } - ++ + public void testMergeOverlapping22() { - ++ + Range ke1 = new KeyExtent(new Text("tab1"), new Text("Bank"), null).toMetadataRange(); + Range ke2 = new KeyExtent(new Text("tab1"), new Text("Fails"), new Text("Bank")).toMetadataRange(); + Range ke3 = new KeyExtent(new Text("tab1"), new Text("Sam"), new Text("Fails")).toMetadataRange(); + Range ke4 = new KeyExtent(new Text("tab1"), new Text("bails"), new Text("Sam")).toMetadataRange(); + Range ke5 = new KeyExtent(new Text("tab1"), null, new Text("bails")).toMetadataRange(); - ++ + List rl = nrl(ke1, ke2, ke3, ke4, ke5); + List expected = nrl(new KeyExtent(new Text("tab1"), null, null).toMetadataRange()); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(ke1, ke2, ke4, ke5); + expected = nrl(new KeyExtent(new Text("tab1"), new Text("Fails"), null).toMetadataRange(), + new KeyExtent(new Text("tab1"), null, new Text("Sam")).toMetadataRange()); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(ke2, ke3, ke4, ke5); + expected = nrl(new KeyExtent(new Text("tab1"), null, new Text("Bank")).toMetadataRange()); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(ke1, ke2, ke3, ke4); + expected = nrl(new KeyExtent(new Text("tab1"), new Text("bails"), null).toMetadataRange()); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(ke2, ke3, ke4); + expected = nrl(new KeyExtent(new Text("tab1"), new Text("bails"), new Text("Bank")).toMetadataRange()); + check(Range.mergeOverlapping(rl), expected); + } - ++ + public void testMergeOverlapping21() { + for (boolean b1 : new boolean[] {true, false}) + for (boolean b2 : new boolean[] {true, false}) + for (boolean b3 : new boolean[] {true, false}) + for (boolean b4 : new boolean[] {true, false}) { - ++ + // System.out.println("b1:"+b1+" b2:"+b2+" b3:"+b3+" b4:"+b4); - ++ + List rl = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("m")), b2), new Range(new Key(new Text("b")), b3, + new Key(new Text("n")), b4)); + List expected = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("n")), b4)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("m")), b2), new Range(new Key(new Text("a")), b3, new Key(new Text("n")), b4)); + expected = nrl(new Range(new Key(new Text("a")), b1 || b3, new Key(new Text("n")), b4)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("n")), b2), new Range(new Key(new Text("b")), b3, new Key(new Text("n")), b4)); + expected = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("n")), b2 || b4)); + check(Range.mergeOverlapping(rl), expected); - ++ + rl = nrl(new Range(new Key(new Text("a")), b1, new Key(new Text("n")), b2), new Range(new Key(new Text("a")), b3, new Key(new Text("n")), b4)); + expected = nrl(new Range(new Key(new Text("a")), b1 || b3, new Key(new Text("n")), b2 || b4)); + check(Range.mergeOverlapping(rl), expected); + } - ++ + } - ++ + public void testEqualsNull() { - ++ + assertTrue(nr(null, "d").equals(nr(null, "d"))); - ++ + assertTrue(nr(null, null).equals(nr(null, null))); - ++ + assertTrue(nr("a", null).equals(nr("a", null))); - ++ + assertFalse(nr(null, "d").equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr(null, "d"))); - ++ + assertFalse(nr(null, null).equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr(null, null))); - ++ + assertFalse(nr("a", null).equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr("a", null))); + } - ++ + public void testEquals() { + assertFalse(nr("b", "d").equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr("b", "d"))); - ++ + assertFalse(nr("x", "y").equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr("x", "y"))); - ++ + assertFalse(nr("a", "z").equals(nr("a", "d"))); + assertFalse(nr("a", "d").equals(nr("a", "z"))); - ++ + assertTrue(nr("a", "z").equals(nr("a", "z"))); + } - ++ + public void testRow1() { + Range rowRange = new Range(new Text("r1")); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertFalse(rowRange.contains(new Key(new Text("r11")))); + assertFalse(rowRange.contains(new Key(new Text("r0")))); + } - ++ + public void testRow2() { + Range rowRange = new Range(new Text("r1"), new Text("r2")); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r2")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r0")))); + assertFalse(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow3() { + Range rowRange = new Range(new Text("r1"), false, new Text("r2"), false); - ++ + assertFalse(rowRange.contains(new Key(new Text("r1")))); + assertFalse(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertFalse(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r2")))); + assertFalse(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertFalse(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r0")))); + assertFalse(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow4() { + Range rowRange = new Range(new Text("r1"), true, new Text("r2"), false); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r2")))); + assertFalse(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertFalse(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r0")))); + assertFalse(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow5() { + Range rowRange = new Range(new Text("r1"), false, new Text("r2"), true); - ++ + assertFalse(rowRange.contains(new Key(new Text("r1")))); + assertFalse(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertFalse(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r2")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r0")))); + assertFalse(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow6() { + Range rowRange = new Range(new Text("r1"), true, null, true); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r2")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertFalse(rowRange.contains(new Key(new Text("r0")))); + assertTrue(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow7() { + Range rowRange = new Range(null, true, new Text("r2"), true); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r2")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r0")))); + assertFalse(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + public void testRow8() { + Range rowRange = new Range((Text) null); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r1"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r1")).followingKey(PartialKey.ROW))); + assertTrue(rowRange.contains(new Key(new Text("r11")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r2")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1")))); + assertTrue(rowRange.contains(new Key(new Text("r2"), new Text("cf1"), new Text("cq1")))); - ++ + assertTrue(rowRange.contains(new Key(new Text("r0")))); + assertTrue(rowRange.contains(new Key(new Text("r2")).followingKey(PartialKey.ROW))); + } - ++ + private static Range nr(String r1, boolean r1i, String r2, boolean r2i) { + Text tr1 = null; + Text tr2 = null; - ++ + if (r1 != null) + tr1 = new Text(r1); - ++ + if (r2 != null) + tr2 = new Text(r2); - ++ + return new Range(tr1, r1i, tr2, r2i); - ++ + } - ++ + private static Key nk(String r) { + return new Key(new Text(r)); + } - ++ + public void testClip1() { + Range fence = nr("a", false, "c", false); - ++ + runClipTest(fence, nr("a", false, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", false, "c", true), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", true), nr("a", false, "c", false)); - ++ + fence = nr("a", true, "c", false); - ++ + runClipTest(fence, nr("a", false, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", false), nr("a", true, "c", false)); + runClipTest(fence, nr("a", false, "c", true), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", true), nr("a", true, "c", false)); - ++ + fence = nr("a", false, "c", true); - ++ + runClipTest(fence, nr("a", false, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", false, "c", true), nr("a", false, "c", true)); + runClipTest(fence, nr("a", true, "c", true), nr("a", false, "c", true)); - ++ + fence = nr("a", true, "c", true); - ++ + runClipTest(fence, nr("a", false, "c", false), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", false), nr("a", true, "c", false)); + runClipTest(fence, nr("a", false, "c", true), nr("a", false, "c", true)); + runClipTest(fence, nr("a", true, "c", true), nr("a", true, "c", true)); + } - ++ + public void testClip2() { + Range fence = nr("a", false, "c", false); - ++ + runClipTest(fence, nr(null, true, null, true), nr("a", false, "c", false)); + runClipTest(fence, nr(null, true, "c", true), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, null, true), nr("a", false, "c", false)); + runClipTest(fence, nr("a", true, "c", true), nr("a", false, "c", false)); + } - ++ + public void testClip3() { + Range fence = nr("a", false, "c", false); - ++ + runClipTest(fence, nr("0", false, "z", false), nr("a", false, "c", false)); + runClipTest(fence, nr("0", true, "z", false), nr("a", false, "c", false)); + runClipTest(fence, nr("0", false, "z", true), nr("a", false, "c", false)); + runClipTest(fence, nr("0", true, "z", true), nr("a", false, "c", false)); - ++ + runClipTest(fence, nr("0", false, "b", false), nr("a", false, "b", false)); + runClipTest(fence, nr("0", true, "b", false), nr("a", false, "b", false)); + runClipTest(fence, nr("0", false, "b", true), nr("a", false, "b", true)); + runClipTest(fence, nr("0", true, "b", true), nr("a", false, "b", true)); - ++ + runClipTest(fence, nr("a1", false, "z", false), nr("a1", false, "c", false)); + runClipTest(fence, nr("a1", true, "z", false), nr("a1", true, "c", false)); + runClipTest(fence, nr("a1", false, "z", true), nr("a1", false, "c", false)); + runClipTest(fence, nr("a1", true, "z", true), nr("a1", true, "c", false)); - ++ + runClipTest(fence, nr("a1", false, "b", false), nr("a1", false, "b", false)); + runClipTest(fence, nr("a1", true, "b", false), nr("a1", true, "b", false)); + runClipTest(fence, nr("a1", false, "b", true), nr("a1", false, "b", true)); + runClipTest(fence, nr("a1", true, "b", true), nr("a1", true, "b", true)); + } - ++ + public void testClip4() { + Range fence = new Range(nk("c"), false, nk("n"), false); - ++ + runClipTest(fence, new Range(nk("a"), false, nk("c"), false)); + runClipTest(fence, new Range(nk("a"), false, nk("c"), true)); + runClipTest(fence, new Range(nk("n"), false, nk("r"), false)); + runClipTest(fence, new Range(nk("n"), true, nk("r"), false)); + runClipTest(fence, new Range(nk("a"), true, nk("b"), false)); + runClipTest(fence, new Range(nk("a"), true, nk("b"), true)); - ++ + fence = new Range(nk("c"), true, nk("n"), true); - ++ + runClipTest(fence, new Range(nk("a"), false, nk("c"), false)); + runClipTest(fence, new Range(nk("a"), false, nk("c"), true), new Range(nk("c"), true, nk("c"), true)); + runClipTest(fence, new Range(nk("n"), false, nk("r"), false)); + runClipTest(fence, new Range(nk("n"), true, nk("r"), false), new Range(nk("n"), true, nk("n"), true)); + runClipTest(fence, new Range(nk("q"), false, nk("r"), false)); + runClipTest(fence, new Range(nk("q"), true, nk("r"), false)); - ++ + fence = nr("b", true, "b", true); - ++ + runClipTest(fence, nr("b", false, "c", false)); + runClipTest(fence, nr("b", true, "c", false), nr("b", true, "b", true)); + runClipTest(fence, nr("a", false, "b", false)); + runClipTest(fence, nr("a", false, "b", true), nr("b", true, "b", true)); - ++ + } - ++ + public void testBug1() { - ++ + // unit test related to a bug that was observed (bug was not in range, but want to ensure the following works) - ++ + // clip caught the scanner going to a tablet passed the end of the scan range + Range fence = new Range(new Text("10<"), false, new Text("~"), true); - ++ + Key k1 = new Key(new Text("10<"), new Text("~tab"), new Text("~pr")); + Range range = new Range(k1, true, k1.followingKey(PartialKey.ROW), false); - ++ + runClipTest(fence, range); - ++ + // scanner was not handling edge case properly... + Range scanRange = new Range(new Key("10;007cdc5b0".getBytes(), "~tab".getBytes(), "~pr".getBytes(), "".getBytes(), 130962, false), false, new Key(new Text( + "10<")).followingKey(PartialKey.ROW), false); + // below is the proper check the scanner now does instead of just comparing the row bytes + scanRange.afterEndKey(new Key(new Text("10<")).followingKey(PartialKey.ROW)); + } - ++ + private void runClipTest(Range fence, Range range) { + try { + fence.clip(range); + assertFalse(true); + } catch (IllegalArgumentException e) { - ++ + } - ++ + } - ++ + private void runClipTest(Range fence, Range range, Range expected) { + Range clipped = fence.clip(range); + assertEquals(expected, clipped); + } - ++ + private static Key nk(String r, String cf, String cq) { + return new Key(new Text(r), new Text(cf), new Text(cq)); + } - ++ + private static Key nk(String r, String cf, String cq, String cv) { + return new Key(new Text(r), new Text(cf), new Text(cq), new Text(cv)); + } - ++ + private static Column nc(String cf, String cq) { + return new Column(cf.getBytes(), cq == null ? null : cq.getBytes(), null); + } - ++ + private static Column nc(String cf) { + return nc(cf, null); + } - ++ + private static Range nr(String row) { + return new Range(new Text(row)); + } - ++ + public void testBound1() { + Range range1 = nr("row1"); - ++ + Range range2 = range1.bound(nc("b"), nc("e")); - ++ + assertFalse(range2.contains(nk("row1"))); + assertFalse(range2.contains(nk("row1", "a", "z"))); + assertTrue(range2.contains(nk("row1", "b", ""))); + assertTrue(range2.contains(nk("row1", "b", "z"))); + assertTrue(range2.contains(nk("row1", "c", "z"))); + assertTrue(range2.contains(nk("row1", "e", ""))); + assertTrue(range2.contains(nk("row1", "e", "z"))); + assertFalse(range2.contains(nk("row1", "e", "").followingKey(PartialKey.ROW_COLFAM))); + assertFalse(range2.contains(nk("row1", "f", ""))); + assertFalse(range2.contains(nk("row1", "f", "z"))); - ++ + } - ++ + public void testBound2() { + Range range1 = new Range(nk("row1", "b", "x"), true, nk("row1", "f", "x"), true); - ++ + Range range2 = range1.bound(nc("a"), nc("g")); + assertEquals(range1, range2); + assertFalse(range2.contains(nk("row1", "a", "x"))); + assertTrue(range2.contains(nk("row1", "b", "x"))); + assertTrue(range2.contains(nk("row1", "f", "x"))); + assertFalse(range2.contains(nk("row1", "g", ""))); - ++ + Range range3 = range1.bound(nc("c"), nc("d")); + assertFalse(range3.contains(nk("row1", "b", "x"))); + assertTrue(range3.contains(nk("row1", "c", ""))); + assertTrue(range3.contains(nk("row1", "c", "z"))); + assertTrue(range3.contains(nk("row1", "d", ""))); + assertTrue(range3.contains(nk("row1", "d", "z"))); + assertFalse(range3.contains(nk("row1", "e", ""))); + assertFalse(range3.contains(nk("row1", "f", "x"))); - ++ + Range range4 = range1.bound(nc("c", "w"), nc("d", "z")); + assertFalse(range4.contains(nk("row1", "b", "x"))); + assertTrue(range4.contains(nk("row1", "c", "w"))); + assertTrue(range4.contains(nk("row1", "c", "w", ""))); + assertTrue(range4.contains(nk("row1", "c", "w", "a"))); + assertTrue(range4.contains(nk("row1", "d", "z", ""))); + assertTrue(range4.contains(nk("row1", "d", "z", "a"))); + assertFalse(range4.contains(nk("row1", "d", "{", ""))); + assertFalse(range4.contains(nk("row1", "d", "z", "a").followingKey(PartialKey.ROW_COLFAM_COLQUAL))); + assertFalse(range4.contains(nk("row1", "f", "x"))); - ++ + Range range5 = range1.bound(nc("b", "w"), nc("f", "z")); + assertEquals(range1, range5); + assertFalse(range5.contains(nk("row1", "b", "w"))); + assertTrue(range5.contains(nk("row1", "b", "x"))); + assertTrue(range5.contains(nk("row1", "f", "x"))); + assertFalse(range5.contains(nk("row1", "f", "z"))); - ++ + Range range6 = range1.bound(nc("b", "y"), nc("f", "w")); + assertFalse(range6.contains(nk("row1", "b", "x"))); + assertTrue(range6.contains(nk("row1", "b", "y"))); + assertTrue(range6.contains(nk("row1", "f", "w"))); + assertTrue(range6.contains(nk("row1", "f", "w", "a"))); + assertFalse(range6.contains(nk("row1", "f", "w").followingKey(PartialKey.ROW_COLFAM_COLQUAL))); + assertFalse(range6.contains(nk("row1", "f", "x"))); - ++ + Range range7 = range1.bound(nc("a", "y"), nc("g", "w")); + assertEquals(range1, range7); + assertFalse(range7.contains(nk("row1", "b", "w"))); + assertTrue(range7.contains(nk("row1", "b", "x"))); + assertTrue(range7.contains(nk("row1", "f", "x"))); + assertFalse(range7.contains(nk("row1", "f", "z"))); + } - ++ + public void testString() { + Range r1 = new Range(new Text("r1")); + Range r2 = new Range("r1"); + assertEquals(r1, r2); - ++ + r1 = new Range(new Text("r1"), new Text("r2")); + r2 = new Range("r1", "r2"); + assertEquals(r1, r2); - ++ + r1 = new Range(new Text("r1"), false, new Text("r2"), true); + r2 = new Range("r1", false, "r2", true); + assertEquals(r1, r2); - ++ + r1 = new Range(new Text("r1"), true, new Text("r2"), false); + r2 = new Range("r1", true, "r2", false); + assertEquals(r1, r2); - ++ + } - ++ + public void testExactRange() { + Range r = Range.exact("abc"); + assertTrue(r.contains(new Key("abc"))); + assertTrue(r.contains(new Key("abc", "def"))); + assertFalse(r.contains(new Key("abcd"))); + assertFalse(r.contains(new Key("abb"))); + assertFalse(r.contains(new Key("abd"))); - ++ + r = Range.exact("abc", "def"); + assertTrue(r.contains(new Key("abc", "def", "ghi"))); + assertFalse(r.contains(new Key("abc", "defg"))); + assertFalse(r.contains(new Key("abc", "dee"))); + assertFalse(r.contains(new Key("abc", "deg"))); - ++ + r = Range.exact("abc", "def", "ghi"); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&k"))); + assertFalse(r.contains(new Key("abc", "def", "ghij"))); + assertFalse(r.contains(new Key("abc", "def", "ghh"))); + assertFalse(r.contains(new Key("abc", "def", "ghj"))); - ++ + r = Range.exact("abc", "def", "ghi", "j&k"); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&k", 7l))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&kl"))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&j"))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&l"))); - ++ + r = Range.exact("abc", "def", "ghi", "j&k", 7l); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&k", 7l))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&k", 6l))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&k", 8l))); + } - ++ + public void testPrefixRange() { + Range r = Range.prefix("abc"); + assertTrue(r.contains(new Key("abc"))); + assertTrue(r.contains(new Key("abc", "def"))); + assertTrue(r.contains(new Key("abcd"))); + assertFalse(r.contains(new Key("abb"))); + assertFalse(r.contains(new Key("abd"))); - ++ + r = Range.prefix("abc", "def"); + assertTrue(r.contains(new Key("abc", "def", "ghi"))); + assertTrue(r.contains(new Key("abc", "defg"))); + assertFalse(r.contains(new Key("abc", "dee"))); + assertFalse(r.contains(new Key("abc", "deg"))); - ++ + r = Range.prefix("abc", "def", "ghi"); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&k"))); + assertTrue(r.contains(new Key("abc", "def", "ghij"))); + assertFalse(r.contains(new Key("abc", "def", "ghh"))); + assertFalse(r.contains(new Key("abc", "def", "ghj"))); - ++ + r = Range.prefix("abc", "def", "ghi", "j&k"); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&k", 7l))); + assertTrue(r.contains(new Key("abc", "def", "ghi", "j&kl"))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&j"))); + assertFalse(r.contains(new Key("abc", "def", "ghi", "j&l"))); - ++ + r = Range.prefix(makeText((byte) 0x07, (byte) 0xff)); + assertTrue(r.contains(new Key(makeText((byte) 0x07, (byte) 0xff)))); + assertTrue(r.contains(new Key(makeText((byte) 0x07, (byte) 0xff, (byte) 0x00)))); + assertFalse(r.contains(new Key(makeText((byte) 0x07, (byte) 0xfe)))); + assertFalse(r.contains(new Key(makeText((byte) 0x08)))); - ++ + r = Range.prefix(makeText((byte) 0xff)); + assertTrue(r.isInfiniteStopKey()); + assertTrue(r.contains(new Key(makeText((byte) 0xff)))); + assertTrue(r.contains(new Key(makeText((byte) 0xff, (byte) 0x07)))); - ++ + r = Range.prefix(new Text("abc"), makeText((byte) 0xff)); + assertTrue(r.contains(new Key(new Text("abc"), makeText((byte) 0xff)))); + assertTrue(r.contains(new Key(new Text("abc"), makeText((byte) 0xff, (byte) 0x07)))); + assertFalse(r.contains(new Key(new Text("abcd")))); + assertFalse(r.contains(new Key(new Text("abd")))); - ++ + r = Range.prefix(new Text("abc"), new Text("def"), makeText((byte) 0xff)); + assertTrue(r.contains(new Key(new Text("abc"), new Text("def"), makeText((byte) 0xff)))); + assertTrue(r.contains(new Key(new Text("abc"), new Text("def"), makeText((byte) 0xff, (byte) 0x07)))); + assertFalse(r.contains(new Key(new Text("abc"), new Text("defg")))); + assertFalse(r.contains(new Key(new Text("abc"), new Text("deg")))); - ++ + r = Range.prefix(new Text("abc"), new Text("def"), new Text("ghi"), makeText((byte) 0xff)); + assertTrue(r.contains(new Key(new Text("abc"), new Text("def"), new Text("ghi"), makeText((byte) 0xff)))); + assertTrue(r.contains(new Key(new Text("abc"), new Text("def"), new Text("ghi"), makeText((byte) 0xff, (byte) 0x07)))); + assertFalse(r.contains(new Key(new Text("abc"), new Text("def"), new Text("ghij")))); + assertFalse(r.contains(new Key(new Text("abc"), new Text("def"), new Text("ghj")))); + } - ++ + public static Text makeText(byte... b) { + return new Text(b); + } - ++ + public void testPrefix() { + assertEquals(Range.followingPrefix(makeText((byte) 0x07)), new Text(makeText((byte) 0x08))); + assertEquals(Range.followingPrefix(makeText((byte) 0xfe)), new Text(makeText((byte) 0xff))); + assertNull(Range.followingPrefix(makeText((byte) 0xff))); + assertNull(Range.followingPrefix(makeText((byte) 0xff, (byte) 0xff))); + assertEquals(Range.followingPrefix(makeText((byte) 0x07, (byte) 0xff)), new Text(makeText((byte) 0x08))); + } + + public void testReadFields() throws Exception { + Range r = nr("nuts", "soup"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + r.write(dos); + dos.close(); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + Range r2 = new Range(); + r2.readFields(dis); + dis.close(); + + assertEquals(r, r2); + } + + public void testReadFields_Check() throws Exception { + Range r = new Range(new Key(new Text("soup")), true, false, new Key(new Text("nuts")), true, false); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + r.write(dos); + dos.close(); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + Range r2 = new Range(); + try { + r2.readFields(dis); + fail("readFields allowed invalid range"); + } catch (InvalidObjectException exc) { + /* good! */ + } finally { + dis.close(); + } + } + + public void testThrift() { + Range r = nr("nuts", "soup"); + TRange tr = r.toThrift(); + Range r2 = new Range(tr); + assertEquals(r, r2); + } + + public void testThrift_Check() { + Range r = new Range(new Key(new Text("soup")), true, false, new Key(new Text("nuts")), true, false); + TRange tr = r.toThrift(); + try { ++ @SuppressWarnings("unused") + Range r2 = new Range(tr); + fail("Thrift constructor allowed invalid range"); + } catch (IllegalArgumentException exc) { + /* good! */ + } + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/c84acfc9/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooCache.java ---------------------------------------------------------------------- diff --cc fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooCache.java index c9c77b8,0000000..af37b10 mode 100644,000000..100644 --- a/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooCache.java +++ b/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooCache.java @@@ -1,319 -1,0 +1,317 @@@ +/* + * 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.accumulo.fate.zookeeper; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; - import java.io.Closeable; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.KeeperException.Code; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.data.Stat; + +/** + * Caches values stored in zookeeper and keeps them up to date as they change in zookeeper. + * + */ - public class ZooCache implements Closeable { ++public class ZooCache { + private static final Logger log = Logger.getLogger(ZooCache.class); - ++ + private ZCacheWatcher watcher = new ZCacheWatcher(); + private Watcher externalWatcher = null; - ++ + private HashMap cache; + private HashMap statCache; + private HashMap> childrenCache; - ++ + private ZooReader zReader; - ++ + private ZooKeeper getZooKeeper() { + return zReader.getZooKeeper(); + } - ++ + private class ZCacheWatcher implements Watcher { + @Override + public void process(WatchedEvent event) { - ++ + if (log.isTraceEnabled()) + log.trace(event); - ++ + switch (event.getType()) { + case NodeDataChanged: + case NodeChildrenChanged: + case NodeCreated: + case NodeDeleted: + remove(event.getPath()); + break; + case None: + switch (event.getState()) { + case Disconnected: + if (log.isTraceEnabled()) + log.trace("Zoo keeper connection disconnected, clearing cache"); + clear(); + break; + case SyncConnected: + break; + case Expired: + if (log.isTraceEnabled()) + log.trace("Zoo keeper connection expired, clearing cache"); + clear(); + break; + default: + log.warn("Unhandled: " + event); + } + break; + default: + log.warn("Unhandled: " + event); + } - ++ + if (externalWatcher != null) { + externalWatcher.process(event); + } + } + } - ++ + public ZooCache(String zooKeepers, int sessionTimeout) { + this(zooKeepers, sessionTimeout, null); + } - ++ + public ZooCache(String zooKeepers, int sessionTimeout, Watcher watcher) { + this(new ZooReader(zooKeepers, sessionTimeout), watcher); + } - ++ + public ZooCache(ZooReader reader, Watcher watcher) { + this.zReader = reader; + this.cache = new HashMap(); + this.statCache = new HashMap(); + this.childrenCache = new HashMap>(); + this.externalWatcher = watcher; + } - ++ + private static interface ZooRunnable { + void run(ZooKeeper zooKeeper) throws KeeperException, InterruptedException; + } - ++ + private synchronized void retry(ZooRunnable op) { - ++ + int sleepTime = 100; - ++ + while (true) { - ++ + ZooKeeper zooKeeper = getZooKeeper(); - ++ + try { + op.run(zooKeeper); + return; - ++ + } catch (KeeperException e) { + if (e.code() == Code.NONODE) { + log.error("Looked up non existant node in cache " + e.getPath(), e); + } + log.warn("Zookeeper error, will retry", e); + } catch (InterruptedException e) { + log.info("Zookeeper error, will retry", e); + } catch (ConcurrentModificationException e) { + log.debug("Zookeeper was modified, will retry"); + } - ++ + try { + // do not hold lock while sleeping + wait(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (sleepTime < 10000) + sleepTime = (int) (sleepTime + sleepTime * Math.random()); - ++ + } + } - ++ + public synchronized List getChildren(final String zPath) { - ++ + ZooRunnable zr = new ZooRunnable() { - ++ + @Override + public void run(ZooKeeper zooKeeper) throws KeeperException, InterruptedException { - ++ + if (childrenCache.containsKey(zPath)) + return; - ++ + try { + List children = zooKeeper.getChildren(zPath, watcher); + childrenCache.put(zPath, children); + } catch (KeeperException ke) { + if (ke.code() != Code.NONODE) { + throw ke; + } + } + } - ++ + }; - ++ + retry(zr); - ++ + List children = childrenCache.get(zPath); + if (children == null) { + return null; + } + return Collections.unmodifiableList(children); + } - ++ + public synchronized byte[] get(final String zPath) { + return get(zPath, null); + } - ++ + public synchronized byte[] get(final String zPath, Stat stat) { + ZooRunnable zr = new ZooRunnable() { - ++ + @Override + public void run(ZooKeeper zooKeeper) throws KeeperException, InterruptedException { - ++ + if (cache.containsKey(zPath)) + return; - ++ + /* + * The following call to exists() is important, since we are caching that a node does not exist. Once the node comes into existance, it will be added to + * the cache. But this notification of a node coming into existance will only be given if exists() was previously called. + * + * If the call to exists() is bypassed and only getData() is called with a special case that looks for Code.NONODE in the KeeperException, then + * non-existance can not be cached. + */ - ++ + Stat stat = zooKeeper.exists(zPath, watcher); - ++ + byte[] data = null; - ++ + if (stat == null) { + if (log.isTraceEnabled()) + log.trace("zookeeper did not contain " + zPath); + } else { + try { + data = zooKeeper.getData(zPath, watcher, stat); + } catch (KeeperException.BadVersionException e1) { + throw new ConcurrentModificationException(); + } catch (KeeperException.NoNodeException e2) { + throw new ConcurrentModificationException(); + } + if (log.isTraceEnabled()) + log.trace("zookeeper contained " + zPath + " " + (data == null ? null : new String(data))); + } + if (log.isTraceEnabled()) + log.trace("putting " + zPath + " " + (data == null ? null : new String(data)) + " in cache"); + put(zPath, data, stat); + } - ++ + }; - ++ + retry(zr); - ++ + if (stat != null) { + Stat cstat = statCache.get(zPath); + if (cstat != null) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + cstat.write(dos); + dos.close(); - ++ + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + stat.readFields(dis); - ++ + dis.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } - ++ + return cache.get(zPath); + } - ++ + private synchronized void put(String zPath, byte[] data, Stat stat) { + cache.put(zPath, data); + statCache.put(zPath, stat); + } - ++ + private synchronized void remove(String zPath) { + if (log.isTraceEnabled()) + log.trace("removing " + zPath + " from cache"); + cache.remove(zPath); + childrenCache.remove(zPath); + statCache.remove(zPath); + } - ++ + public synchronized void clear() { + cache.clear(); + childrenCache.clear(); + statCache.clear(); + } - ++ + public synchronized void clear(String zPath) { - ++ + for (Iterator i = cache.keySet().iterator(); i.hasNext();) { + String path = i.next(); + if (path.startsWith(zPath)) + i.remove(); + } - ++ + for (Iterator i = childrenCache.keySet().iterator(); i.hasNext();) { + String path = i.next(); + if (path.startsWith(zPath)) + i.remove(); + } - ++ + for (Iterator i = statCache.keySet().iterator(); i.hasNext();) { + String path = i.next(); + if (path.startsWith(zPath)) + i.remove(); + } + } - ++ + private static Map instances = new HashMap(); - ++ + public static synchronized ZooCache getInstance(String zooKeepers, int sessionTimeout) { + String key = zooKeepers + ":" + sessionTimeout; + ZooCache zc = instances.get(key); + if (zc == null) { + zc = new ZooCache(zooKeepers, sessionTimeout); + instances.put(key, zc); + } - ++ + return zc; + } - - @Override ++ + public void close() { + cache.clear(); + statCache.clear(); + childrenCache.clear(); + zReader.close(); + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/c84acfc9/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java ---------------------------------------------------------------------- diff --cc fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java index 5fc9595,0000000..b8f606d mode 100644,000000..100644 --- a/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java +++ b/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java @@@ -1,118 -1,0 +1,117 @@@ +/* + * 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.accumulo.fate.zookeeper; + - import java.io.Closeable; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + ++import org.apache.zookeeper.AsyncCallback.VoidCallback; +import org.apache.zookeeper.KeeperException; ++import org.apache.zookeeper.KeeperException.Code; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooKeeper; - import org.apache.zookeeper.AsyncCallback.VoidCallback; - import org.apache.zookeeper.KeeperException.Code; +import org.apache.zookeeper.data.Stat; + - public class ZooReader implements IZooReader, Closeable { - ++public class ZooReader implements IZooReader { ++ + protected String keepers; + protected int timeout; - ++ + protected ZooKeeper getSession(String keepers, int timeout, String scheme, byte[] auth) { + return ZooSession.getSession(keepers, timeout, scheme, auth); + } - ++ + protected ZooKeeper getZooKeeper() { + return getSession(keepers, timeout, null, null); + } - ++ + @Override + public byte[] getData(String zPath, Stat stat) throws KeeperException, InterruptedException { + return getZooKeeper().getData(zPath, false, stat); + } - ++ + @Override + public Stat getStatus(String zPath) throws KeeperException, InterruptedException { + return getZooKeeper().exists(zPath, false); + } - ++ + @Override + public Stat getStatus(String zPath, Watcher watcher) throws KeeperException, InterruptedException { + return getZooKeeper().exists(zPath, watcher); + } - ++ + @Override + public List getChildren(String zPath) throws KeeperException, InterruptedException { + return getZooKeeper().getChildren(zPath, false); + } - ++ + @Override + public List getChildren(String zPath, Watcher watcher) throws KeeperException, InterruptedException { + return getZooKeeper().getChildren(zPath, watcher); + } - ++ + @Override + public boolean exists(String zPath) throws KeeperException, InterruptedException { + return getZooKeeper().exists(zPath, false) != null; + } - ++ + @Override + public boolean exists(String zPath, Watcher watcher) throws KeeperException, InterruptedException { + return getZooKeeper().exists(zPath, watcher) != null; + } - ++ + @Override + public void sync(final String path) throws KeeperException, InterruptedException { + final AtomicInteger rc = new AtomicInteger(); + final AtomicBoolean waiter = new AtomicBoolean(false); + getZooKeeper().sync(path, new VoidCallback() { + @Override + public void processResult(int code, String arg1, Object arg2) { + rc.set(code); + synchronized (waiter) { + waiter.set(true); + waiter.notifyAll(); + } - }}, null); ++ } ++ }, null); + synchronized (waiter) { + while (!waiter.get()) + waiter.wait(); + } + Code code = Code.get(rc.get()); + if (code != KeeperException.Code.OK) { + throw KeeperException.create(code); + } - } - ++ } ++ + public ZooReader(String keepers, int timeout) { + this.keepers = keepers; + this.timeout = timeout; + } + + /** - * Closes this reader. If closure of the underlying session is interrupted, - * this method sets the calling thread's interrupt status. ++ * Closes this reader. If closure of the underlying session is interrupted, this method sets the calling thread's interrupt status. + */ + public void close() { + try { + getZooKeeper().close(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +}