Bug 2697: Improvement wrong response handling, missing message
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ConfigTransactionControllerImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.config.manager.impl;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11 import static java.lang.String.format;
12
13 import com.google.common.collect.Lists;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Set;
21 import java.util.concurrent.atomic.AtomicBoolean;
22 import javax.annotation.Nullable;
23 import javax.annotation.concurrent.GuardedBy;
24 import javax.management.DynamicMBean;
25 import javax.management.InstanceAlreadyExistsException;
26 import javax.management.InstanceNotFoundException;
27 import javax.management.MBeanServer;
28 import javax.management.ObjectName;
29 import org.opendaylight.controller.config.api.DependencyResolver;
30 import org.opendaylight.controller.config.api.ModuleIdentifier;
31 import org.opendaylight.controller.config.api.ValidationException;
32 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
33 import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
34 import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
35 import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWritableWrapper;
36 import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean;
37 import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl;
38 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
39 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
40 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
41 import org.opendaylight.controller.config.spi.Module;
42 import org.opendaylight.controller.config.spi.ModuleFactory;
43 import org.opendaylight.yangtools.concepts.Identifiable;
44 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
45 import org.osgi.framework.BundleContext;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 /**
49  * This is a JMX bean representing current transaction. It contains
50  * transaction identifier, unique version and parent version for
51  * optimistic locking.
52  */
53 class ConfigTransactionControllerImpl implements
54         ConfigTransactionControllerInternal,
55         ConfigTransactionControllerImplMXBean,
56         Identifiable<TransactionIdentifier> {
57     private static final Logger LOG = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
58
59     private final ConfigTransactionLookupRegistry txLookupRegistry;
60     private final ObjectName controllerON;
61
62     private final long parentVersion, currentVersion;
63     private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder;
64     private final DependencyResolverManager dependencyResolverManager;
65     private final TransactionStatus transactionStatus;
66     private final MBeanServer transactionsMBeanServer;
67     private final Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories;
68
69     /**
70      * Disables ability of {@link DynamicWritableWrapper} to change attributes
71      * during validation.
72      */
73     @GuardedBy("this")
74     private final AtomicBoolean configBeanModificationDisabled = new AtomicBoolean(
75             false);
76     private final ReadOnlyAtomicBoolean readOnlyAtomicBoolean = new ReadOnlyAtomicBooleanImpl(
77             configBeanModificationDisabled);
78     private final MBeanServer configMBeanServer;
79
80     private final boolean blankTransaction;
81
82     @GuardedBy("this")
83     private final SearchableServiceReferenceWritableRegistry writableSRRegistry;
84
85     public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
86                                            long parentVersion, CodecRegistry codecRegistry, long currentVersion,
87                                            Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
88                                            MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
89                                            boolean blankTransaction, SearchableServiceReferenceWritableRegistry  writableSRRegistry) {
90         this.txLookupRegistry = txLookupRegistry;
91         String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
92         this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
93         this.parentVersion = parentVersion;
94         this.currentVersion = currentVersion;
95         this.currentlyRegisteredFactories = currentlyRegisteredFactories;
96         this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
97         this.transactionStatus = new TransactionStatus();
98         this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
99                 transactionStatus, writableSRRegistry, codecRegistry, transactionsMBeanServer);
100         this.transactionsMBeanServer = transactionsMBeanServer;
101         this.configMBeanServer = configMBeanServer;
102         this.blankTransaction = blankTransaction;
103         this.writableSRRegistry = writableSRRegistry;
104     }
105
106     @Override
107     public void copyExistingModulesAndProcessFactoryDiff(Collection<ModuleInternalInfo> existingModules, List<ModuleFactory> lastListOfFactories) {
108         // copy old configuration to this server
109         for (ModuleInternalInfo oldConfigInfo : existingModules) {
110             try {
111                 copyExistingModule(oldConfigInfo);
112             } catch (InstanceAlreadyExistsException e) {
113                 throw new IllegalStateException("Error while copying " + oldConfigInfo, e);
114             }
115         }
116         processDefaultBeans(lastListOfFactories);
117     }
118
119     private synchronized void processDefaultBeans(List<ModuleFactory> lastListOfFactories) {
120         transactionStatus.checkNotCommitStarted();
121         transactionStatus.checkNotAborted();
122
123         Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
124         Set<ModuleFactory> newSet = new HashSet<>(factoriesHolder.getModuleFactories());
125
126         List<ModuleFactory> toBeAdded = new ArrayList<>();
127         List<ModuleFactory> toBeRemoved = new ArrayList<>();
128         for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) {
129             if (oldSet.contains(moduleFactory) == false) {
130                 toBeAdded.add(moduleFactory);
131             }
132         }
133         for (ModuleFactory moduleFactory : lastListOfFactories) {
134             if (newSet.contains(moduleFactory) == false) {
135                 toBeRemoved.add(moduleFactory);
136             }
137         }
138         // add default modules
139         for (ModuleFactory moduleFactory : toBeAdded) {
140             BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
141             Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
142                     bundleContext);
143             for (Module module : defaultModules) {
144                 // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
145                 DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
146                 try {
147                     boolean defaultBean = true;
148                     putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null,
149                             dependencyResolver, defaultBean, bundleContext);
150                 } catch (InstanceAlreadyExistsException e) {
151                     throw new IllegalStateException(e);
152                 }
153             }
154         }
155
156         // remove modules belonging to removed factories
157         for (ModuleFactory removedFactory : toBeRemoved) {
158             List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
159             for (ModuleIdentifier name : modulesOfRemovedFactory) {
160                 destroyModule(name);
161             }
162         }
163     }
164
165
166     private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException {
167
168         transactionStatus.checkNotCommitStarted();
169         transactionStatus.checkNotAborted();
170         ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
171         dependencyResolverManager.assertNotExists(moduleIdentifier);
172
173         ModuleFactory moduleFactory;
174         BundleContext bc;
175         try {
176             moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());
177             bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
178         } catch (InstanceNotFoundException e) {
179             throw new IllegalStateException(e);
180         }
181
182         Module module;
183         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
184         try {
185
186             module = moduleFactory.createModule(
187                     moduleIdentifier.getInstanceName(), dependencyResolver,
188                     oldConfigBeanInfo.getReadableModule(), bc);
189         } catch (Exception e) {
190             throw new IllegalStateException(format(
191                     "Error while copying old configuration from %s to %s",
192                     oldConfigBeanInfo, moduleFactory), e);
193         }
194         putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver,
195                 oldConfigBeanInfo.isDefaultBean(), bc);
196     }
197
198     @Override
199     public synchronized ObjectName createModule(String factoryName,
200                                                 String instanceName) throws InstanceAlreadyExistsException {
201
202         transactionStatus.checkNotCommitStarted();
203         transactionStatus.checkNotAborted();
204         ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
205         dependencyResolverManager.assertNotExists(moduleIdentifier);
206
207         // find factory
208         ModuleFactory moduleFactory;
209         try {
210             moduleFactory = factoriesHolder.findByModuleName(factoryName);
211         } catch (InstanceNotFoundException e) {
212             throw new IllegalArgumentException(e);
213         }
214         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
215         BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
216         Module module = moduleFactory.createModule(instanceName, dependencyResolver,
217                 bundleContext);
218         boolean defaultBean = false;
219         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
220                 moduleFactory, null, dependencyResolver, defaultBean, bundleContext);
221     }
222
223     private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
224             ModuleIdentifier moduleIdentifier, Module module,
225             ModuleFactory moduleFactory,
226             @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver,
227             boolean isDefaultBean, BundleContext bundleContext)
228             throws InstanceAlreadyExistsException {
229
230         LOG.debug("Adding module {} to transaction {}", moduleIdentifier, this);
231         if (moduleIdentifier.equals(module.getIdentifier()) == false) {
232             throw new IllegalStateException("Incorrect name reported by module. Expected "
233                     + moduleIdentifier + ", got " + module.getIdentifier());
234         }
235         if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false) {
236             throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
237                     + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
238         }
239         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
240                 module, moduleIdentifier, getTransactionIdentifier(),
241                 readOnlyAtomicBoolean, transactionsMBeanServer,
242                 configMBeanServer);
243
244         ObjectName writableON = ObjectNameUtil.createTransactionModuleON(
245                 getTransactionIdentifier().getName(), moduleIdentifier);
246         // put wrapper to jmx
247         TransactionModuleJMXRegistration transactionModuleJMXRegistration = getTxModuleJMXRegistrator()
248                 .registerMBean(writableDynamicWrapper, writableON);
249
250         dependencyResolverManager.put(
251                 moduleIdentifier, module, moduleFactory,
252                 maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean, bundleContext);
253         return writableON;
254     }
255
256     @Override
257     public synchronized void destroyModule(ObjectName objectName) throws InstanceNotFoundException {
258         checkTransactionName(objectName);
259         ObjectNameUtil.checkDomain(objectName);
260         ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName,
261                 ObjectNameUtil.TYPE_MODULE);
262         destroyModule(moduleIdentifier);
263     }
264
265     private void checkTransactionName(ObjectName objectName) {
266         String foundTransactionName = ObjectNameUtil
267                 .getTransactionName(objectName);
268         if (getTransactionIdentifier().getName().equals(foundTransactionName) == false) {
269             throw new IllegalArgumentException("Wrong transaction name "
270                     + objectName);
271         }
272     }
273
274     private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) {
275         LOG.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
276         transactionStatus.checkNotAborted();
277
278         ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
279         if (blankTransaction == false &&
280                 found.isDefaultBean()) {
281             LOG.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
282         }
283         // first remove refNames, it checks for objectname existence
284
285         try {
286             writableSRRegistry.removeServiceReferences(
287                     ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier));
288         } catch (InstanceNotFoundException e) {
289             LOG.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry);
290             throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e);
291         }
292
293         ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager.destroyModule(moduleIdentifier);
294         // remove from jmx
295         removedTInfo.getTransactionModuleJMXRegistration().close();
296     }
297
298     @Override
299     public long getParentVersion() {
300         return parentVersion;
301     }
302
303     @Override
304     public long getVersion() {
305         return currentVersion;
306     }
307
308     @Override
309     public synchronized void validateConfig() throws ValidationException {
310         if (configBeanModificationDisabled.get()) {
311             throw new IllegalStateException("Cannot start validation");
312         }
313         configBeanModificationDisabled.set(true);
314         try {
315             validateNoLocks();
316         } finally {
317             configBeanModificationDisabled.set(false);
318         }
319     }
320
321     private void validateNoLocks() throws ValidationException {
322         transactionStatus.checkNotAborted();
323         LOG.trace("Validating transaction {}", getTransactionIdentifier());
324         // call validate()
325         List<ValidationException> collectedExceptions = new ArrayList<>();
326         for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
327                 .getAllModules().entrySet()) {
328             ModuleIdentifier name = entry.getKey();
329             Module module = entry.getValue();
330             try {
331                 module.validate();
332             } catch (Exception e) {
333                 LOG.warn("Validation exception in {}", getTransactionName(),
334                         e);
335                 collectedExceptions.add(ValidationException
336                         .createForSingleException(name, e));
337             }
338         }
339         if (!collectedExceptions.isEmpty()) {
340             throw ValidationException
341                     .createFromCollectedValidationExceptions(collectedExceptions);
342         }
343         LOG.trace("Validated transaction {}", getTransactionIdentifier());
344     }
345
346     /**
347      * If this method passes validation, it will grab
348      * {@link TransactionStatus#secondPhaseCommitStarted} lock. This lock will
349      * prevent calling @{link #validateBeforeCommitAndLockTransaction},
350      * effectively only allowing to call {@link #secondPhaseCommit} after
351      * successful return of this method.
352      */
353     @Override
354     public synchronized CommitInfo validateBeforeCommitAndLockTransaction()
355             throws ValidationException {
356         transactionStatus.checkNotAborted();
357         transactionStatus.checkNotCommitStarted();
358         configBeanModificationDisabled.set(true);
359         try {
360             validateNoLocks();
361         } catch (ValidationException e) {
362             LOG.trace("Commit failed on validation");
363             configBeanModificationDisabled.set(false); // recoverable error
364             throw e;
365         }
366         // errors in this state are not recoverable. modules are not mutable
367         // anymore.
368         transactionStatus.setSecondPhaseCommitStarted();
369         return dependencyResolverManager.toCommitInfo();
370     }
371
372     /**
373      * {@inheritDoc}
374      */
375     @Override
376     public synchronized List<ModuleIdentifier> secondPhaseCommit() {
377         transactionStatus.checkNotAborted();
378         transactionStatus.checkCommitStarted();
379         if (configBeanModificationDisabled.get() == false) {
380             throw new IllegalStateException(
381                     "Internal error - validateBeforeCommitAndLockTransaction should be called "
382                             + "to obtain a lock");
383         }
384
385         LOG.trace("Committing transaction {}", getTransactionIdentifier());
386
387         Map<ModuleIdentifier, Module> allModules = dependencyResolverManager.getAllModules();
388
389         // call getInstance() on all Modules from top to bottom (from source to target of the dependency relation)
390         // The source of a dependency closes itself and calls getInstance recursively on the dependencies (in case of reconfiguration)
391         // This makes close() calls from top to bottom while createInstance() calls are performed bottom to top
392         List<ModuleIdentifier> sortedModuleIdentifiers = Lists.reverse(dependencyResolverManager.getSortedModuleIdentifiers());
393         for (ModuleIdentifier moduleIdentifier : sortedModuleIdentifiers) {
394             Module module = allModules.get(moduleIdentifier);
395
396             try {
397                 LOG.debug("About to commit {} in transaction {}",
398                         moduleIdentifier, getTransactionIdentifier());
399                 AutoCloseable instance = module.getInstance();
400                 checkNotNull(instance, "Instance is null:{} in transaction {}", moduleIdentifier, getTransactionIdentifier());
401             } catch (Exception e) {
402                 LOG.error("Commit failed on {} in transaction {}", moduleIdentifier,
403                         getTransactionIdentifier(), e);
404                 internalAbort();
405                 throw new IllegalStateException(
406                         format("Error - getInstance() failed for %s in transaction %s",
407                                 moduleIdentifier, getTransactionIdentifier()), e);
408             }
409         }
410
411         LOG.trace("Committed configuration {}", getTransactionIdentifier());
412         transactionStatus.setCommitted();
413
414         return sortedModuleIdentifiers;
415     }
416
417     @Override
418     public synchronized void abortConfig() {
419         transactionStatus.checkNotCommitStarted();
420         transactionStatus.checkNotAborted();
421         internalAbort();
422     }
423
424     private void internalAbort() {
425         LOG.trace("Aborting {}", this);
426         transactionStatus.setAborted();
427         close();
428     }
429
430     public void close() {
431         dependencyResolverManager.close();
432         txLookupRegistry.close();
433     }
434
435     @Override
436     public ObjectName getControllerObjectName() {
437         return controllerON;
438     }
439
440     @Override
441     public String getTransactionName() {
442         return getTransactionIdentifier().getName();
443     }
444
445     /**
446      * {@inheritDoc}
447      */
448     @Override
449     public Set<ObjectName> lookupConfigBeans() {
450         return txLookupRegistry.lookupConfigBeans();
451     }
452
453     /**
454      * {@inheritDoc}
455      */
456     @Override
457     public Set<ObjectName> lookupConfigBeans(String moduleName) {
458         return txLookupRegistry.lookupConfigBeans(moduleName);
459     }
460
461     /**
462      * {@inheritDoc}
463      */
464     @Override
465     public ObjectName lookupConfigBean(String moduleName, String instanceName)
466             throws InstanceNotFoundException {
467         return txLookupRegistry.lookupConfigBean(moduleName, instanceName);
468     }
469
470     /**
471      * {@inheritDoc}
472      */
473     @Override
474     public Set<ObjectName> lookupConfigBeans(String moduleName, String instanceName) {
475         return txLookupRegistry.lookupConfigBeans(moduleName, instanceName);
476     }
477
478     /**
479      * {@inheritDoc}
480      */
481     @Override
482     public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
483         txLookupRegistry.checkConfigBeanExists(objectName);
484     }
485     // --
486
487     /**
488      * {@inheritDoc}
489      */
490     @Override
491     public Set<String> getAvailableModuleNames() {
492         return factoriesHolder.getModuleNames();
493     }
494
495     @Override
496     public boolean isClosed() {
497         return transactionStatus.isAbortedOrCommitted();
498     }
499
500     @Override
501     public String toString() {
502         StringBuilder sb = new StringBuilder();
503         sb.append("transactionName=");
504         sb.append(getTransactionName());
505         return sb.toString();
506     }
507
508     // @VisibleForTesting
509
510     TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() {
511         return txLookupRegistry.getTxModuleJMXRegistrator();
512     }
513
514     public TransactionIdentifier getName() {
515         return getTransactionIdentifier();
516     }
517
518     @Override
519     public List<ModuleFactory> getCurrentlyRegisteredFactories() {
520         return new ArrayList<>(factoriesHolder.getModuleFactories());
521     }
522
523     @Override
524     public TransactionIdentifier getIdentifier() {
525         return getTransactionIdentifier();
526     }
527
528     @Override
529     public BundleContext getModuleFactoryBundleContext(String factoryName) {
530         Map.Entry<ModuleFactory, BundleContext> factoryBundleContextEntry = this.currentlyRegisteredFactories.get(factoryName);
531         if (factoryBundleContextEntry == null || factoryBundleContextEntry.getValue() == null) {
532             throw new NullPointerException("Bundle context of " + factoryName + " ModuleFactory not found.");
533         }
534         return factoryBundleContextEntry.getValue();
535     }
536
537     // service reference functionality:
538
539
540     @Override
541     public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
542         return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
543     }
544
545     @Override
546     public synchronized Map<String, Map<String, ObjectName>> getServiceMapping() {
547         return writableSRRegistry.getServiceMapping();
548     }
549
550     @Override
551     public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
552         return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
553     }
554
555     @Override
556     public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
557         return writableSRRegistry.lookupServiceInterfaceNames(objectName);
558     }
559
560     @Override
561     public synchronized String getServiceInterfaceName(String namespace, String localName) {
562         return writableSRRegistry.getServiceInterfaceName(namespace, localName);
563     }
564
565     @Override
566     public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
567         return writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, moduleON);
568     }
569
570     @Override
571     public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException {
572         writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
573     }
574
575     @Override
576     public synchronized void removeAllServiceReferences() {
577         writableSRRegistry.removeAllServiceReferences();
578     }
579
580     @Override
581     public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
582         return writableSRRegistry.removeServiceReferences(objectName);
583     }
584
585     @Override
586     public SearchableServiceReferenceWritableRegistry  getWritableRegistry() {
587         return writableSRRegistry;
588     }
589
590     @Override
591     public TransactionIdentifier getTransactionIdentifier() {
592         return txLookupRegistry.getTransactionIdentifier();
593     }
594
595     @Override
596     public Set<String> getAvailableModuleFactoryQNames() {
597         return txLookupRegistry.getAvailableModuleFactoryQNames();
598     }
599
600     @Override
601     public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
602         writableSRRegistry.checkServiceReferenceExists(objectName);
603     }
604
605     @Override
606     public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
607         return writableSRRegistry.getServiceReference(serviceInterfaceQName, refName);
608     }
609 }