2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.restconf.nb.rfc8040.handlers;
10 import com.google.common.base.Preconditions;
11 import java.util.Collection;
12 import java.util.concurrent.atomic.AtomicInteger;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
15 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
16 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
17 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
18 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
19 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.MonitoringModule;
20 import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
21 import org.opendaylight.yangtools.concepts.ListenerRegistration;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
25 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
28 import org.opendaylight.yangtools.yang.model.api.Module;
29 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * Implementation of {@link SchemaContextHandler}.
38 @SuppressWarnings("checkstyle:FinalClass")
39 public class SchemaContextHandler implements SchemaContextListenerHandler, AutoCloseable {
41 private static final Logger LOG = LoggerFactory.getLogger(SchemaContextHandler.class);
43 private static final SchemaContextHandler INSTANCE = new SchemaContextHandler();
45 private final AtomicInteger moduleSetId = new AtomicInteger(0);
47 private TransactionChainHandler transactionChainHandler;
48 private DOMSchemaService domSchemaService;
49 private ListenerRegistration<SchemaContextListener> listenerRegistration;
51 private volatile SchemaContext schemaContext;
56 * @param transactionChainHandler Transaction chain handler
58 private SchemaContextHandler(final TransactionChainHandler transactionChainHandler,
59 final DOMSchemaService domSchemaService) {
60 this.transactionChainHandler = transactionChainHandler;
61 this.domSchemaService = domSchemaService;
65 private SchemaContextHandler() {
69 public static SchemaContextHandler instance() {
73 public static SchemaContextHandler newInstance(TransactionChainHandler transactionChainHandler,
74 DOMSchemaService domSchemaService) {
75 INSTANCE.transactionChainHandler = transactionChainHandler;
76 INSTANCE.domSchemaService = domSchemaService;
81 listenerRegistration = domSchemaService.registerSchemaContextListener(this);
86 if (listenerRegistration != null) {
87 listenerRegistration.close();
92 @SuppressWarnings("checkstyle:hiddenField")
93 public void onGlobalContextUpdated(final SchemaContext context) {
94 Preconditions.checkNotNull(context);
95 schemaContext = context;
97 final Module ietfYangLibraryModule =
98 context.findModule(IetfYangLibrary.MODULE_QNAME).orElse(null);
99 if (ietfYangLibraryModule != null) {
100 NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode =
101 RestconfMappingNodeUtil.mapModulesByIetfYangLibraryYang(context.getModules(), ietfYangLibraryModule,
102 context, String.valueOf(this.moduleSetId.incrementAndGet()));
106 final Module monitoringModule =
107 schemaContext.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
108 if (monitoringModule != null) {
109 NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode =
110 RestconfMappingNodeUtil.mapCapabilites(monitoringModule);
116 public SchemaContext get() {
117 return schemaContext;
120 private void putData(
121 final NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode) {
122 final DOMDataWriteTransaction wTx = this.transactionChainHandler.get().newWriteOnlyTransaction();
123 wTx.put(LogicalDatastoreType.OPERATIONAL,
124 YangInstanceIdentifier.create(NodeIdentifier.create(normNode.getNodeType())), normNode);
126 wTx.submit().checkedGet();
127 } catch (final TransactionCommitFailedException e) {
128 if (!(e.getCause() instanceof ConflictingModificationAppliedException)) {
129 throw new RestconfDocumentedException("Problem occurred while putting data to DS.", e);
133 Ignore error when another cluster node is already putting the same data to DS.
134 We expect that cluster is homogeneous and that node was going to write the same data
135 (that means no retry is needed). Transaction chain reset must be invoked to be able
136 to continue writing data with another transaction after failed transaction.
137 This is workaround for bug:
138 https://bugs.opendaylight.org/show_bug.cgi?id=7728
140 LOG.warn("Ignoring that another cluster node is already putting the same data to DS.", e);
141 this.transactionChainHandler.reset();