Java tutorial
/** * 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.curator.x.rpc; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.generated.*; import org.apache.curator.retry.RetryOneTime; import org.apache.curator.test.BaseClassForTests; import org.apache.curator.test.InstanceSpec; import org.apache.curator.test.Timing; import org.apache.curator.utils.CloseableUtils; import org.apache.curator.utils.ThreadUtils; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.node.ObjectNode; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.nio.ByteBuffer; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; public class RpcTests extends BaseClassForTests { private Timing timing = new Timing(); private CuratorProjectionServer thriftServer; private CuratorService.Client curatorServiceClient; private EventService.Client eventServiceClient; private int thriftPort; @BeforeMethod @Override public void setup() throws Exception { super.setup(); ObjectMapper mapper = new ObjectMapper(); ObjectNode connectionNode = mapper.createObjectNode(); connectionNode.put("name", "test"); connectionNode.put("connectionString", server.getConnectString()); ObjectNode thriftNode = mapper.createObjectNode(); thriftPort = InstanceSpec.getRandomPort(); thriftNode.put("port", thriftPort); ArrayNode connections = mapper.createArrayNode(); connections.add(connectionNode); ObjectNode node = mapper.createObjectNode(); node.put("connections", connections); node.put("thrift", thriftNode); final String configurationJson = mapper.writeValueAsString(node); thriftServer = CuratorProjectionServer.startServer(configurationJson); TSocket clientTransport = new TSocket("localhost", thriftPort); clientTransport.setTimeout(timing.connection()); clientTransport.open(); TProtocol clientProtocol = new TBinaryProtocol(clientTransport); curatorServiceClient = new CuratorService.Client(clientProtocol); TSocket eventTransport = new TSocket("localhost", thriftPort); eventTransport.setTimeout(timing.connection()); eventTransport.open(); TProtocol eventProtocol = new TBinaryProtocol(eventTransport); eventServiceClient = new EventService.Client(eventProtocol); } @AfterMethod @Override public void teardown() throws Exception { thriftServer.stop(); super.teardown(); } @Test public void testBasic() throws Exception { CuratorProjection curatorProjection = curatorServiceClient.newCuratorProjection("test"); CreateSpec spec = new CreateSpec(); spec.path = "/test"; spec.data = ByteBuffer.wrap("value".getBytes()); OptionalPath node = curatorServiceClient.createNode(curatorProjection, spec); Assert.assertEquals(node.path, "/test"); GetDataSpec dataSpec = new GetDataSpec(); dataSpec.path = "/test"; OptionalData data = curatorServiceClient.getData(curatorProjection, dataSpec); Assert.assertEquals(data.data, ByteBuffer.wrap("value".getBytes())); } @Test public void testEvents() throws Exception { final CuratorProjection curatorProjection = curatorServiceClient.newCuratorProjection("test"); final CountDownLatch connectedLatch = new CountDownLatch(1); final CountDownLatch nodeCreatedLatch = new CountDownLatch(1); Callable<Void> proc = new Callable<Void>() { @Override public Void call() throws Exception { while (!Thread.currentThread().isInterrupted()) { CuratorEvent event = eventServiceClient.getNextEvent(curatorProjection); if (event.type == CuratorEventType.CONNECTION_CONNECTED) { connectedLatch.countDown(); } else if (event.type == CuratorEventType.WATCHED) { if (event.watchedEvent.eventType == EventType.NodeCreated) { nodeCreatedLatch.countDown(); } } } return null; } }; Future<Void> eventFuture = ThreadUtils.newSingleThreadExecutor("test").submit(proc); Assert.assertTrue(timing.awaitLatch(connectedLatch)); ExistsSpec spec = new ExistsSpec(); spec.path = "/test"; spec.watched = true; curatorServiceClient.exists(curatorProjection, spec); CreateSpec createSpec = new CreateSpec(); createSpec.path = "/test"; curatorServiceClient.createNode(curatorProjection, createSpec); Assert.assertTrue(timing.awaitLatch(nodeCreatedLatch)); eventFuture.cancel(true); } @Test public void testLockMultiThread() throws Exception { final Timing timing = new Timing(); TSocket clientTransport = new TSocket("localhost", thriftPort); clientTransport.setTimeout(timing.connection()); clientTransport.open(); TProtocol clientProtocol = new TBinaryProtocol(clientTransport); final CuratorService.Client secondCuratorServiceClient = new CuratorService.Client(clientProtocol); ExecutorService service = ThreadUtils.newFixedThreadPool(2, "test"); ExecutorCompletionService<Void> completer = new ExecutorCompletionService<Void>(service); final CountDownLatch lockLatch = new CountDownLatch(2); final AtomicBoolean hasTheLock = new AtomicBoolean(); for (int i = 0; i < 2; ++i) { final CuratorService.Client client = (i == 0) ? curatorServiceClient : secondCuratorServiceClient; Callable<Void> proc = new Callable<Void>() { @Override public Void call() throws Exception { CuratorProjection curatorProjection = client.newCuratorProjection("test"); OptionalLockProjection lockProjection = client.acquireLock(curatorProjection, "/lock", timing.forWaiting().milliseconds()); if (lockProjection.lockProjection == null) { throw new Exception("Could not acquire lock"); } try { if (!hasTheLock.compareAndSet(false, true)) { throw new Exception("Two lockers"); } timing.sleepABit(); } finally { hasTheLock.set(false); lockLatch.countDown(); client.closeGenericProjection(curatorProjection, lockProjection.lockProjection.id); } return null; } }; completer.submit(proc); } completer.take().get(); completer.take().get(); Assert.assertTrue(timing.awaitLatch(lockLatch)); service.shutdownNow(); } @Test public void testRecoverableException() throws Exception { CuratorProjection curatorProjection = curatorServiceClient.newCuratorProjection("test"); CreateSpec spec = new CreateSpec(); spec.path = "/this/wont/work"; spec.data = ByteBuffer.wrap("value".getBytes()); try { curatorServiceClient.createNode(curatorProjection, spec); Assert.fail("Should have failed"); } catch (CuratorException e) { Assert.assertEquals(e.getType(), ExceptionType.NODE); Assert.assertNotNull(e.nodeException); Assert.assertEquals(e.nodeException, NodeExceptionType.NONODE); } } @Test public void testEphemeralCleanup() throws Exception { CuratorProjection curatorProjection = curatorServiceClient.newCuratorProjection("test"); CreateSpec spec = new CreateSpec(); spec.path = "/test"; spec.data = ByteBuffer.wrap("value".getBytes()); spec.mode = CreateMode.EPHEMERAL; OptionalPath node = curatorServiceClient.createNode(curatorProjection, spec); System.out.println(node); final CountDownLatch latch = new CountDownLatch(1); CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1)); try { client.start(); Watcher watcher = new Watcher() { @Override public void process(WatchedEvent event) { if (event.getType() == Event.EventType.NodeDeleted) { latch.countDown(); } } }; client.checkExists().usingWatcher(watcher).forPath("/test"); curatorServiceClient.closeCuratorProjection(curatorProjection); Assert.assertTrue(timing.awaitLatch(latch)); } finally { CloseableUtils.closeQuietly(client); } } }