/*
* 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.console.demo;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteServices;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.console.demo.service.DemoCachesLoadService;
import org.apache.ignite.console.demo.service.DemoRandomCacheLoadService;
import org.apache.ignite.console.demo.service.DemoServiceClusterSingleton;
import org.apache.ignite.console.demo.service.DemoServiceKeyAffinity;
import org.apache.ignite.console.demo.service.DemoServiceMultipleInstances;
import org.apache.ignite.console.demo.service.DemoServiceNodeSingleton;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.logger.slf4j.Slf4jLogger;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_JETTY_PORT;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_QUIET;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER;
import static org.apache.ignite.console.demo.AgentDemoUtils.newScheduledThreadPool;
import static org.apache.ignite.events.EventType.EVTS_DISCOVERY;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_REST_JETTY_ADDRS;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_REST_JETTY_PORT;
/**
* Demo for cluster features like SQL and Monitoring.
*
* Cache will be created and populated with data to query.
*/
public class AgentClusterDemo {
/** */
private static final Logger log = LoggerFactory.getLogger(AgentClusterDemo.class);
/** */
private static final AtomicBoolean initGuard = new AtomicBoolean();
/** */
private static CountDownLatch initLatch = new CountDownLatch(1);
/** */
private static volatile String demoUrl;
/** */
private static final int NODE_CNT = 3;
/**
* Configure node.
* @param basePort Base port.
* @param gridIdx Ignite instance name index.
* @param client If {@code true} then start client node.
* @return IgniteConfiguration
*/
private static IgniteConfiguration igniteConfiguration(int basePort, int gridIdx, boolean client) {
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setIgniteInstanceName((client ? "demo-client-" : "demo-server-" ) + gridIdx);
cfg.setLocalHost("127.0.0.1");
cfg.setEventStorageSpi(new MemoryEventStorageSpi());
cfg.setIncludeEventTypes(EVTS_DISCOVERY);
cfg.getConnectorConfiguration().setPort(basePort);
System.setProperty(IGNITE_JETTY_PORT, String.valueOf(basePort + 10));
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
int discoPort = basePort + 20;
ipFinder.setAddresses(Collections.singletonList("127.0.0.1:" + discoPort + ".." + (discoPort + NODE_CNT - 1)));
// Configure discovery SPI.
TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
discoSpi.setLocalPort(discoPort);
discoSpi.setIpFinder(ipFinder);
cfg.setDiscoverySpi(discoSpi);
TcpCommunicationSpi commSpi = new TcpCommunicationSpi();
commSpi.setSharedMemoryPort(-1);
commSpi.setMessageQueueLimit(10);
int commPort = basePort + 30;
commSpi.setLocalPort(commPort);
cfg.setCommunicationSpi(commSpi);
cfg.setGridLogger(new Slf4jLogger(log));
cfg.setMetricsLogFrequency(0);
if (client)
cfg.setClientMode(true);
return cfg;
}
/**
* Starts read and write from cache in background.
*
* @param services Distributed services on the grid.
*/
private static void deployServices(IgniteServices services) {
services.deployMultiple("Demo service: Multiple instances", new DemoServiceMultipleInstances(), 7, 3);
services.deployNodeSingleton("Demo service: Node singleton", new DemoServiceNodeSingleton());
services.deployClusterSingleton("Demo service: Cluster singleton", new DemoServiceClusterSingleton());
services.deployKeyAffinitySingleton("Demo service: Key affinity singleton",
new DemoServiceKeyAffinity(), DemoCachesLoadService.CAR_CACHE_NAME, "id");
services.deployClusterSingleton("Demo caches load service", new DemoCachesLoadService(20));
services.deployNodeSingleton("RandomCache load service", new DemoRandomCacheLoadService(20));
}
/** */
public static String getDemoUrl() {
return demoUrl;
}
/**
* Start ignite node with cacheEmployee and populate it with data.
*/
public static CountDownLatch tryStart() {
if (initGuard.compareAndSet(false, true)) {
log.info("DEMO: Starting embedded nodes for demo...");
System.setProperty(IGNITE_NO_ASCII, "true");
System.setProperty(IGNITE_QUIET, "false");
System.setProperty(IGNITE_UPDATE_NOTIFIER, "false");
System.setProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE, "1");
System.setProperty(IGNITE_PERFORMANCE_SUGGESTIONS_DISABLED, "true");
final AtomicInteger basePort = new AtomicInteger(60700);
final AtomicInteger cnt = new AtomicInteger(-1);
final ScheduledExecutorService execSrv = newScheduledThreadPool(1, "demo-nodes-start");
execSrv.scheduleAtFixedRate(new Runnable() {
@Override public void run() {
int idx = cnt.incrementAndGet();
int port = basePort.get();
try {
IgniteEx ignite = (IgniteEx)Ignition.start(igniteConfiguration(port, idx, idx == NODE_CNT));
if (idx == 0) {
Collection<String> jettyAddrs = ignite.localNode().attribute(ATTR_REST_JETTY_ADDRS);
if (jettyAddrs == null) {
ignite.cluster().stopNodes();
throw new IgniteException("DEMO: Failed to start Jetty REST server on embedded node");
}
String jettyHost = jettyAddrs.iterator().next();
Integer jettyPort = ignite.localNode().attribute(ATTR_REST_JETTY_PORT);
if (F.isEmpty(jettyHost) || jettyPort == null)
throw new IgniteException("DEMO: Failed to start Jetty REST handler on embedded node");
log.info("DEMO: Started embedded node for demo purpose [TCP binary port={}, Jetty REST port={}]", port, jettyPort);
demoUrl = String.format("http://%s:%d", jettyHost, jettyPort);
initLatch.countDown();
deployServices(ignite.services());
}
}
catch (Throwable e) {
if (idx == 0) {
basePort.getAndAdd(50);
log.warn("DEMO: Failed to start embedded node.", e);
}
else
log.error("DEMO: Failed to start embedded node.", e);
}
finally {
if (idx == NODE_CNT) {
log.info("DEMO: All embedded nodes for demo successfully started");
execSrv.shutdown();
}
}
}
}, 1, 10, TimeUnit.SECONDS);
}
return initLatch;
}
/** */
public static void stop() {
demoUrl = null;
Ignition.stopAll(true);
initLatch = new CountDownLatch(1);
initGuard.compareAndSet(true, false);
}
}