X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fconfig%2Fconfig-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fmanager%2Fimpl%2Fosgi%2FBlankTransactionServiceTracker.java;h=2649b145d0509badbcd88897ca99a83282bed6b5;hp=720b7197ea6100b0890ee0fd4a89d5f5de9157bd;hb=f43b01b81319959b1907e3e04537f5169e7f33d8;hpb=32275b7cbe98c361f08970eff34ecb721f45c9e4 diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java index 720b7197ea..2649b145d0 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013, 2017 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,6 +7,11 @@ */ package org.opendaylight.controller.config.manager.impl.osgi; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.management.ObjectName; import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; @@ -17,64 +22,91 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.management.ObjectName; - /** - * Every time factory is added or removed, blank transaction is triggered to handle - * {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)} - * functionality. + * Every time factory is added or removed, blank transaction is triggered to + * handle. */ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer { - private static final Logger logger = LoggerFactory.getLogger(BlankTransactionServiceTracker.class); + private static final Logger LOG = LoggerFactory.getLogger(BlankTransactionServiceTracker.class); + + public static final int DEFAULT_MAX_ATTEMPTS = 10; - private final ConfigRegistryImpl configRegistry; + private final BlankTransaction blankTransaction; + private final ExecutorService txExecutor; + private final int maxAttempts; - public BlankTransactionServiceTracker(ConfigRegistryImpl configRegistry) { - this.configRegistry = configRegistry; + public BlankTransactionServiceTracker(final ConfigRegistryImpl configRegistry) { + this(() -> { + ObjectName tx = configRegistry.beginConfig(true); + return configRegistry.commitConfig(tx); + }); + } + + public BlankTransactionServiceTracker(final BlankTransaction blankTransaction) { + this(blankTransaction, DEFAULT_MAX_ATTEMPTS, Executors + .newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("config-blank-txn-%d").build())); + } + + @VisibleForTesting + BlankTransactionServiceTracker(final BlankTransaction blankTx, final int maxAttempts, + final ExecutorService txExecutor) { + this.blankTransaction = blankTx; + this.maxAttempts = maxAttempts; + this.txExecutor = txExecutor; } @Override - public Object addingService(ServiceReference moduleFactoryServiceReference) { - blankTransaction(); + public Object addingService(final ServiceReference moduleFactoryServiceReference) { + blankTransactionAsync(); return null; } - synchronized void blankTransaction() { - // race condition check: config-persister might push new configuration while server is starting up. + private void blankTransactionAsync() { + txExecutor.execute(this::blankTransactionSync); + } + + void blankTransactionSync() { + // race condition check: config-persister might push new configuration while + // server is starting up. ConflictingVersionException lastException = null; - int maxAttempts = 10; for (int i = 0; i < maxAttempts; i++) { try { // create transaction - boolean blankTransaction = true; - ObjectName tx = configRegistry.beginConfig(blankTransaction); - CommitStatus commitStatus = configRegistry.commitConfig(tx); - logger.debug("Committed blank transaction with status {}", commitStatus); + CommitStatus commitStatus = blankTransaction.hit(); + LOG.debug("Committed blank transaction with status {}", commitStatus); return; - } catch (ConflictingVersionException e) { + } catch (final ConflictingVersionException e) { lastException = e; try { Thread.sleep(1000); - } catch (InterruptedException interruptedException) { + } catch (final InterruptedException interruptedException) { Thread.currentThread().interrupt(); - throw new IllegalStateException(interruptedException); + LOG.debug("blankTransactionSync was interrupted"); + return; } - } catch (ValidationException e) { - logger.error("Validation exception while running blank transaction indicates programming error", e); - throw new RuntimeException("Validation exception while running blank transaction indicates programming error", e); + } catch (final ValidationException e) { + LOG.error("Validation exception while running blank transaction indicates programming error", e); } } - throw new RuntimeException("Maximal number of attempts reached and still cannot get optimistic lock from " + - "config manager",lastException); + + LOG.error("Maximal number of attempts reached and still cannot get optimistic lock from config manager", + lastException); } @Override - public void modifiedService(ServiceReference moduleFactoryServiceReference, Object o) { - blankTransaction(); + public void modifiedService(final ServiceReference moduleFactoryServiceReference, + final Object object) { + blankTransactionAsync(); } @Override - public void removedService(ServiceReference moduleFactoryServiceReference, Object o) { - blankTransaction(); + public void removedService(final ServiceReference moduleFactoryServiceReference, + final Object object) { + blankTransactionAsync(); + } + + @VisibleForTesting + interface BlankTransaction { + CommitStatus hit() throws ValidationException, ConflictingVersionException; } }