/*
* 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.ignite.internal.processors.service;
import java.util.concurrent.CountDownLatch;
import junit.framework.TestCase;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteServices;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.lang.IgniteFuture;
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceConfiguration;
/**
* Single node services test.
*/
public class GridServiceProcessorMultiNodeSelfTest extends GridServiceProcessorAbstractSelfTest {
/** {@inheritDoc} */
@Override protected int nodeCount() {
return 4;
}
/**
* @throws Exception If failed.
*/
public void testSingletonUpdateTopology() throws Exception {
String name = "serviceSingletonUpdateTopology";
Ignite g = randomGrid();
CountDownLatch latch = new CountDownLatch(1);
DummyService.exeLatch(name, latch);
IgniteServices svcs = g.services();
IgniteFuture<?> fut = svcs.deployClusterSingletonAsync(name, new DummyService());
info("Deployed service: " + name);
fut.get();
info("Finished waiting for service future: " + name);
latch.await();
TestCase.assertEquals(name, 1, DummyService.started(name));
TestCase.assertEquals(name, 0, DummyService.cancelled(name));
int nodeCnt = 2;
startExtraNodes(nodeCnt);
try {
TestCase.assertEquals(name, 1, DummyService.started(name));
TestCase.assertEquals(name, 0, DummyService.cancelled(name));
info(">>> Passed checks.");
checkCount(name, g.services().serviceDescriptors(), 1);
}
finally {
stopExtraNodes(nodeCnt);
}
}
/**
* @throws Exception If failed.
*/
public void testAffinityDeployUpdateTopology() throws Exception {
Ignite g = randomGrid();
final Integer affKey = 1;
// Store a cache key.
g.cache(CACHE_NAME).put(affKey, affKey.toString());
final String name = "serviceAffinityUpdateTopology";
IgniteServices svcs = g.services();
IgniteFuture<?> fut = svcs.deployKeyAffinitySingletonAsync(name, new AffinityService(affKey),
CACHE_NAME, affKey);
info("Deployed service: " + name);
fut.get();
info("Finished waiting for service future: " + name);
checkCount(name, g.services().serviceDescriptors(), 1);
int nodeCnt = 2;
startExtraNodes(nodeCnt);
try {
checkCount(name, g.services().serviceDescriptors(), 1);
}
finally {
stopExtraNodes(nodeCnt);
}
}
/**
* @throws Exception If failed.
*/
public void testDeployOnEachNodeButClientUpdateTopology() throws Exception {
// Prestart client node.
Ignite client = startGrid("client", getConfiguration("client").setClientMode(true));
try {
final String name = "serviceOnEachNodeButClientUpdateTopology";
Ignite g = randomGrid();
CountDownLatch latch = new CountDownLatch(nodeCount());
DummyService.exeLatch(name, latch);
IgniteServices svcs = g.services();
IgniteFuture<?> fut = svcs.deployNodeSingletonAsync(name, new DummyService());
info("Deployed service: " + name);
fut.get();
info("Finished waiting for service future: " + name);
latch.await();
// Ensure service is deployed
assertNotNull(client.services().serviceProxy(name, Service.class, false, 2000));
assertEquals(name, nodeCount(), DummyService.started(name));
assertEquals(name, 0, DummyService.cancelled(name));
int servers = 2;
latch = new CountDownLatch(servers);
DummyService.exeLatch(name, latch);
int clients = 2;
startExtraNodes(servers, clients);
try {
latch.await();
waitForDeployment(name, servers);
// Since we start extra nodes, there may be extra start and cancel events,
// so we check only the difference between start and cancel and
// not start and cancel events individually.
assertEquals(name, nodeCount() + servers, DummyService.started(name) - DummyService.cancelled(name));
checkCount(name, g.services().serviceDescriptors(), nodeCount() + servers);
}
finally {
stopExtraNodes(servers + clients);
}
}
finally {
stopGrid("client");
}
}
/**
* @throws Exception If failed.
*/
public void testDeployOnEachNodeUpdateTopology() throws Exception {
// Prestart client node.
Ignite client = startGrid("client", getConfiguration("client").setClientMode(true));
try {
final String name = "serviceOnEachNodeUpdateTopology";
Ignite g = randomGrid();
final int prestartedNodes = nodeCount() + 1;
CountDownLatch latch = new CountDownLatch(prestartedNodes);
DummyService.exeLatch(name, latch);
ServiceConfiguration srvcCfg = new ServiceConfiguration();
srvcCfg.setNodeFilter(new CacheConfiguration.IgniteAllNodesPredicate());
srvcCfg.setName(name);
srvcCfg.setMaxPerNodeCount(1);
srvcCfg.setService(new DummyService());
IgniteServices svcs = g.services();
IgniteFuture<?> fut = svcs.deployAsync(srvcCfg);
info("Deployed service: " + name);
fut.get();
info("Finished waiting for service future: " + name);
latch.await();
// Ensure service is deployed
assertNotNull(client.services().serviceProxy(name, Service.class, false, 2000));
assertEquals(name, prestartedNodes, DummyService.started(name));
assertEquals(name, 0, DummyService.cancelled(name));
int servers = 2;
int clients = 2;
int extraNodes = servers + clients;
latch = new CountDownLatch(extraNodes);
DummyService.exeLatch(name, latch);
startExtraNodes(servers, clients);
try {
latch.await();
waitForDeployment(name, prestartedNodes + extraNodes);
// Since we start extra nodes, there may be extra start and cancel events,
// so we check only the difference between start and cancel and
// not start and cancel events individually.
assertEquals(name, prestartedNodes + extraNodes,
DummyService.started(name) - DummyService.cancelled(name));
checkCount(name, g.services().serviceDescriptors(), prestartedNodes + extraNodes);
}
finally {
stopExtraNodes(extraNodes);
}
}
finally {
stopGrid("client");
}
}
/**
* @throws Exception If failed.
*/
@SuppressWarnings("deprecation")
public void testDeployLimits() throws Exception {
final String name = "serviceWithLimitsUpdateTopology";
Ignite g = randomGrid();
final int totalInstances = nodeCount() + 1;
CountDownLatch latch = new CountDownLatch(nodeCount());
DummyService.exeLatch(name, latch);
ServiceConfiguration srvcCfg = new ServiceConfiguration();
srvcCfg.setName(name);
srvcCfg.setMaxPerNodeCount(1);
srvcCfg.setTotalCount(totalInstances);
srvcCfg.setService(new DummyService());
IgniteServices svcs = g.services().withAsync();
svcs.deploy(srvcCfg);
IgniteFuture<?> fut = svcs.future();
info("Deployed service: " + name);
fut.get();
info("Finished waiting for service future: " + name);
latch.await();
assertEquals(name, nodeCount(), DummyService.started(name));
assertEquals(name, 0, DummyService.cancelled(name));
checkCount(name, g.services().serviceDescriptors(), nodeCount());
latch = new CountDownLatch(1);
DummyService.exeLatch(name, latch);
int extraNodes = 2;
startExtraNodes(extraNodes);
try {
latch.await();
waitForDeployment(name, totalInstances);
// Since we start extra nodes, there may be extra start and cancel events,
// so we check only the difference between start and cancel and
// not start and cancel events individually.
assertEquals(name, totalInstances, DummyService.started(name) - DummyService.cancelled(name));
checkCount(name, g.services().serviceDescriptors(), totalInstances);
}
finally {
stopExtraNodes(extraNodes);
}
}
}