Author: csierra Date: Mon May 28 14:29:11 2018 New Revision: 1832400 URL: http://svn.apache.org/viewvc?rev=1832400&view=rev Log: [Component-DSL] Support update hints
Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/UpdateSupport.java aries/trunk/component-dsl/component-dsl/src/test/java/org/apache/aries/component/dsl/internal/UpdateSupportTest.java Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java?rev=1832400&r1=1832399&r2=1832400&view=diff ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java (original) +++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/CoalesceOSGiImpl.java Mon May 28 14:29:11 2018 @@ -71,24 +71,26 @@ public class CoalesceOSGiImpl<T> extends synchronized (initialized) { result.close(); - int current = atomicInteger.decrementAndGet(); + UpdateSupport.defer(() -> { + int current = atomicInteger.decrementAndGet(); - if (!initialized.get()) { - return; - } + if (!initialized.get()) { + return; + } - if (pos <= index.get() && current == 0) { - for (int j = pos + 1; j < results.length; j++) { - results[j] = programs[j].run( - bundleContext, publishers[j]); + if (pos <= index.get() && current == 0) { + for (int j = pos + 1; j < results.length; j++) { + results[j] = programs[j].run( + bundleContext, publishers[j]); - index.set(j); + index.set(j); - if (atomicIntegers[j].get() > 0) { - break; + if (atomicIntegers[j].get() > 0) { + break; + } } } - } + }); } }; }; Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java?rev=1832400&r1=1832399&r2=1832400&view=diff ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java (original) +++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationOSGiImpl.java Mon May 28 14:29:11 2018 @@ -92,10 +92,13 @@ public class ConfigurationOSGiImpl exten atomicReference.set(configuration); } - signalLeave(terminatorAtomicReference); - - terminatorAtomicReference.set( - op.apply(configuration.getProperties())); + UpdateSupport.runUpdate(() -> { + signalLeave(terminatorAtomicReference); + + terminatorAtomicReference.set( + op.apply(configuration.getProperties())); + + }); if (closed.get()) { /* Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java?rev=1832400&r1=1832399&r2=1832400&view=diff ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java (original) +++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ConfigurationsOSGiImpl.java Mon May 28 14:29:11 2018 @@ -103,9 +103,11 @@ public class ConfigurationsOSGiImpl exte } ); - signalLeave(pid, terminators); + UpdateSupport.runUpdate(() -> { + signalLeave(pid, terminators); - terminators.put(pid, op.apply(properties)); + terminators.put(pid, op.apply(properties)); + }); if (closed.get()) { /* Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java?rev=1832400&r1=1832399&r2=1832400&view=diff ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java (original) +++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/ServiceReferenceOSGi.java Mon May 28 14:29:11 2018 @@ -79,11 +79,13 @@ public class ServiceReferenceOSGi<T> ServiceReference<T> reference, Tracked<T> tracked) { if (_refresher.test(tracked.cachingServiceReference)) { - tracked.runnable.run(); - tracked.cachingServiceReference = new CachingServiceReference<>( - reference); - tracked.runnable = - _addedSource.apply(tracked.cachingServiceReference); + UpdateSupport.runUpdate(() -> { + tracked.runnable.run(); + tracked.cachingServiceReference = new CachingServiceReference<>( + reference); + tracked.runnable = + _addedSource.apply(tracked.cachingServiceReference); + }); } } Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/UpdateSupport.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/UpdateSupport.java?rev=1832400&view=auto ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/UpdateSupport.java (added) +++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/component/dsl/internal/UpdateSupport.java Mon May 28 14:29:11 2018 @@ -0,0 +1,65 @@ +/* + * 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.aries.component.dsl.internal; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @author Carlos Sierra Andrés + */ +public class UpdateSupport { + + private static final ThreadLocal<Deque<Deque<Runnable>>> + deferredTerminatorsStack = ThreadLocal.withInitial(LinkedList::new); + private static final ThreadLocal<Boolean> isUpdate = + ThreadLocal.withInitial(() -> Boolean.FALSE); + + public static void defer(Runnable runnable) { + if (isUpdate.get()) { + deferredTerminatorsStack.get().peekLast().addLast(runnable); + } + else { + runnable.run(); + } + } + + public static void runUpdate(Runnable runnable) { + isUpdate.set(true); + + Deque<Deque<Runnable>> deferred = deferredTerminatorsStack.get(); + + deferred.addLast(new LinkedList<>()); + + try { + runnable.run(); + } + finally { + Deque<Runnable> terminators = + deferredTerminatorsStack.get().removeLast(); + + for (Runnable terminator : terminators) { + terminator.run(); + } + + if (deferredTerminatorsStack.get().isEmpty()) { + isUpdate.set(false); + } + } + } +} Added: aries/trunk/component-dsl/component-dsl/src/test/java/org/apache/aries/component/dsl/internal/UpdateSupportTest.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/test/java/org/apache/aries/component/dsl/internal/UpdateSupportTest.java?rev=1832400&view=auto ============================================================================== --- aries/trunk/component-dsl/component-dsl/src/test/java/org/apache/aries/component/dsl/internal/UpdateSupportTest.java (added) +++ aries/trunk/component-dsl/component-dsl/src/test/java/org/apache/aries/component/dsl/internal/UpdateSupportTest.java Mon May 28 14:29:11 2018 @@ -0,0 +1,74 @@ +/* + * 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.aries.component.dsl.internal; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * @author Carlos Sierra Andrés + */ +public class UpdateSupportTest { + + @Test + public void testDefer() { + List<Integer> list = new ArrayList<>(); + + UpdateSupport.runUpdate(() -> { + list.add(1); + + UpdateSupport.defer(() -> list.add(3)); + + list.add(2); + }); + + assertEquals(Arrays.asList(1, 2, 3), list); + } + + @Test + public void testDeferStack() { + List<Integer> list = new ArrayList<>(); + + UpdateSupport.runUpdate(() -> { + list.add(1); + + UpdateSupport.defer(() -> list.add(6)); + + UpdateSupport.runUpdate(() -> { + list.add(2); + + UpdateSupport.runUpdate(() -> { + list.add(3); + + UpdateSupport.defer(() -> list.add(4)); + }); + + UpdateSupport.defer(() -> list.add(5)); + }); + }); + + assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6), list); + } + + +} Modified: aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java?rev=1832400&r1=1832399&r2=1832400&view=diff ============================================================================== --- aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java (original) +++ aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/component/dsl/test/DSLTest.java Mon May 28 14:29:11 2018 @@ -346,6 +346,99 @@ public class DSLTest { } @Test + public void testCoalesceWithConfigurationUpdate() + throws IOException, InterruptedException { + + ServiceReference<ConfigurationAdmin> serviceReference = + bundleContext.getServiceReference(ConfigurationAdmin.class); + + ConfigurationAdmin configurationAdmin = bundleContext.getService( + serviceReference); + + Configuration configuration = configurationAdmin.getConfiguration( + "test.configuration"); + + configuration.update(new Hashtable<>()); + + AtomicReference<Dictionary<?,?>> atomicReference = + new AtomicReference<>(null); + + AtomicInteger counter = new AtomicInteger(); + + CountDownLatch countDownLatch = new CountDownLatch(4); + + ServiceRegistration<ManagedService> serviceRegistration = + bundleContext.registerService( + ManagedService.class, __ -> countDownLatch.countDown(), + new Hashtable<String, Object>() {{ + put("service.pid", "test.configuration"); + }}); + + AtomicReference<Runnable> effect = new AtomicReference<>(); + + effect.set(countDownLatch::countDown); + + try(OSGiResult result = + coalesce( + configuration("test.configuration"), + just(Hashtable::new) + ).run( + bundleContext, + x -> { + atomicReference.set(x); + + counter.incrementAndGet(); + + effect.get().run(); + + return NOOP; + })) + { + configuration.update( + new Hashtable<String, Object>() {{ + put("property", "value"); + }} + ); + + countDownLatch.await(10, TimeUnit.SECONDS); + + assertEquals(2, counter.get()); + + assertEquals("value", atomicReference.get().get("property")); + + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + + CountDownLatch deleteLatch = new CountDownLatch(2); + + effect.set(deleteLatch::countDown); + + serviceRegistration = + bundleContext.registerService( + ManagedService.class, __ -> deleteLatch.countDown(), + new Hashtable<String, Object>() {{ + put("service.pid", "test.configuration"); + }}); + + configuration.delete(); + + deleteLatch.await(10, TimeUnit.SECONDS); + + assertEquals(3, counter.get()); + + assertTrue(atomicReference.get().isEmpty()); + } + finally { + bundleContext.ungetService(serviceReference); + + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + } + } + + @Test public void testConfiguration() throws IOException, InterruptedException { ServiceReference<ConfigurationAdmin> serviceReference = bundleContext.getServiceReference(ConfigurationAdmin.class);