/* * 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.felix.scr.integration.components.felix3680; import java.io.StringWriter; import java.util.LinkedHashSet; import java.util.Random; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.osgi.framework.ServiceReference; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.runtime.ServiceComponentRuntime; import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO; import org.osgi.service.log.LogService; public class Main implements Runnable { public static volatile CountDownLatch _enabledLatch; public static volatile CountDownLatch _disabledLatch; public static volatile CountDownLatch _activatedLatch; public static volatile CountDownLatch _deactivatedLatch; private volatile ComponentContext _ctx; private volatile AtomicInteger _counter = new AtomicInteger(); private volatile Random _rnd = new Random(); private volatile LogService _logService; private volatile Thread _thread; private volatile boolean _running; private ServiceComponentRuntime _scr; /** * Helper used to randomly enable or disable a list of components. */ class EnableManager { String[] _componentNames; EnableManager(String[] componentNames) { _componentNames = componentNames; } public void enableComponents(Executor exec) { enableOrDisable(exec, true); } public void disableComponents(Executor exec) { enableOrDisable(exec, false); } private void enableOrDisable(Executor exec, final boolean enable) { for (final int i : getRandomIndexes(_componentNames.length)) { exec.execute(new Runnable() { public void run() { if (enable) { _logService.log(LogService.LOG_INFO, "enabling component " + _componentNames[i]); _ctx.enableComponent(_componentNames[i]); _enabledLatch.countDown(); } else { _logService.log(LogService.LOG_INFO, "disabling component " + _componentNames[i]); _ctx.disableComponent(_componentNames[i]); _disabledLatch.countDown(); } } }); } } private Integer[] getRandomIndexes(int max) { Set<Integer> set = new LinkedHashSet<Integer>(); for (int i = 0; i < max; i++) { int n; do { n = _rnd.nextInt(max); } while (set.contains(n)); set.add(n); } for (int i = 0; i < max; i++) { if (!set.contains(i)) { throw new IllegalStateException("invalid rnd indexes: " + set); } } return set.toArray(new Integer[set.size()]); } } void bindSCR(ServiceComponentRuntime scr) { _scr = scr; } void bindLogService(LogService logService) { _logService = logService; } void bindA(ServiceReference sr) { A a = (A) sr.getBundle().getBundleContext().getService(sr); if (a == null) { throw new IllegalStateException("bindA: bundleContext.getService returned null"); } if (_counter.incrementAndGet() != 1) { throw new IllegalStateException("bindA: invalid counter value: " + _counter); } _enabledLatch.countDown(); } void unbindA(ServiceReference sr) { if (_counter.decrementAndGet() != 0) { throw new IllegalStateException("unbindA: invalid counter value: " + _counter); } _disabledLatch.countDown(); } void start(ComponentContext ctx) { _logService.log(LogService.LOG_INFO, "Main.start"); _ctx = ctx; _running = true; _thread = new Thread(this); _thread.start(); } void stop() { _running = false; _thread.interrupt(); } public void run() { Executor exec = Executors.newFixedThreadPool(50); _logService.log(LogService.LOG_INFO, "Main.run"); int loop = 0; while (_running) { _enabledLatch = new CountDownLatch(11); // for B,C,D,E,F,G,H,I,J,K and Main.bindA() _disabledLatch = new CountDownLatch(11); // for B,C,D,E,F,G,H,I,J,K and Main.unbindA() EnableManager manager = new EnableManager(new String[] { "org.apache.felix.scr.integration.components.felix3680.B", "org.apache.felix.scr.integration.components.felix3680.C", "org.apache.felix.scr.integration.components.felix3680.D", "org.apache.felix.scr.integration.components.felix3680.E", "org.apache.felix.scr.integration.components.felix3680.F", "org.apache.felix.scr.integration.components.felix3680.G", "org.apache.felix.scr.integration.components.felix3680.H", "org.apache.felix.scr.integration.components.felix3680.I", "org.apache.felix.scr.integration.components.felix3680.J", "org.apache.felix.scr.integration.components.felix3680.K" }); manager.enableComponents(exec); try { if (!_enabledLatch.await(10000, TimeUnit.MILLISECONDS)) { System.out.println("Did not get A injected timely ... see logs.txt"); _logService.log(LogService.LOG_ERROR, "enableLatch TIMEOUT"); dumpComponents(); return; } } catch (InterruptedException e) { } manager.disableComponents(exec); try { if (!_disabledLatch.await(10000, TimeUnit.MILLISECONDS)) { System.out.println("Could not disable components timely ... see logs.txt"); _logService.log(LogService.LOG_ERROR, "disableLatch TIMEOUT"); dumpComponents(); return; } } catch (InterruptedException e) { } loop ++; if ((loop % 500) == 0) { _logService.log(LogService.LOG_WARNING, "Performed " + loop + " tests."); } } } private void dumpComponents() { StringWriter sw = new StringWriter(); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.A"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.B"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.C"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.D"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.E"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.F"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.G"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.H"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.I"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.J"); dumpState(sw, "org.apache.felix.scr.integration.components.felix3680.K"); _logService.log(LogService.LOG_WARNING, sw.toString()); } private void dumpState(StringWriter sw, String name) { ComponentDescriptionDTO c = _scr.getComponentDescriptionDTO(_ctx.getBundleContext().getBundle(), name); if ( c != null ) { sw.append( name ).append( "[" ).append( _scr.isComponentEnabled(c)? "enabled":"disabled" ).append( "] " ); } } }