X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-model-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fmodel%2Frepo%2Futil%2FAbstractSchemaRepository.java;h=2413c6fc9679891a49d3a80ab25119b7aadf619c;hb=98ac2b04a469af0b0d69d17ef66799fb46a9c4ed;hp=53563fde69cea887b7d0a90e5be70350f58e8925;hpb=ac4b2ade2f614701d1ae44381b6c2963f15587bb;p=yangtools.git diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java index 53563fde69..2413c6fc96 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java @@ -3,27 +3,28 @@ * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/eplv10.html + * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.model.repo.util; import com.google.common.annotations.Beta; -import com.google.common.collect.HashMultimap; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureFallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; - import javax.annotation.concurrent.GuardedBy; - import org.opendaylight.yangtools.util.concurrent.ExceptionMapper; import org.opendaylight.yangtools.util.concurrent.ReflectiveExceptionMapper; import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException; @@ -56,7 +57,7 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche * a specific representation of a source. */ @GuardedBy("this") - private final Map, AbstractSchemaSourceRegistration>> sources = new HashMap<>(); + private final Map, AbstractSchemaSourceRegistration>> sources = new HashMap<>(); /* * Schema source listeners. @@ -64,11 +65,12 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche @GuardedBy("this") private final Collection listeners = new ArrayList<>(); - private static final CheckedFuture fetchSource(final SourceIdentifier id, final Iterator> it) { + private static CheckedFuture fetchSource(final SourceIdentifier id, final Iterator> it) { final AbstractSchemaSourceRegistration reg = it.next(); @SuppressWarnings("unchecked") final CheckedFuture f = ((SchemaSourceProvider)reg.getProvider()).getSource(id); + return Futures.makeChecked(Futures.withFallback(f, new FutureFallback() { @Override public ListenableFuture create(final Throwable t) throws SchemaSourceException { @@ -78,31 +80,56 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche return fetchSource(id, it); } - throw new MissingSchemaSourceException("All available providers exhausted"); + throw new MissingSchemaSourceException("All available providers exhausted", id, t); } }), FETCH_MAPPER); } @Override public CheckedFuture getSchemaSource(final SourceIdentifier id, final Class representation) { - final Multimap, AbstractSchemaSourceRegistration> srcs = sources.get(id); - if (srcs == null) { - return Futures.immediateFailedCheckedFuture(new MissingSchemaSourceException("No providers registered for source" + id)); + final ArrayList> sortedSchemaSourceRegistrations; + + synchronized (this) { + final ListMultimap, AbstractSchemaSourceRegistration> srcs = sources.get(id); + if (srcs == null) { + return Futures.immediateFailedCheckedFuture(new MissingSchemaSourceException("No providers registered for source" + id, id)); + } + + sortedSchemaSourceRegistrations = Lists.newArrayList(srcs.get(representation)); } - final Iterator> regs = srcs.get(representation).iterator(); + // TODO, remove and make sources keep sorted multimap (e.g. ArrayListMultimap with SortedLists) + Collections.sort(sortedSchemaSourceRegistrations, SchemaProviderCostComparator.INSTANCE); + + final Iterator> regs = sortedSchemaSourceRegistrations.iterator(); if (!regs.hasNext()) { return Futures.immediateFailedCheckedFuture( - new MissingSchemaSourceException("No providers for source " + id + " representation " + representation + " available")); + new MissingSchemaSourceException("No providers for source " + id + " representation " + representation + " available", id)); } - return fetchSource(id, regs); + CheckedFuture fetchSourceFuture = fetchSource(id, regs); + // Add callback to notify cache listeners about encountered schema + Futures.addCallback(fetchSourceFuture, new FutureCallback() { + @Override + public void onSuccess(final T result) { + for (final SchemaListenerRegistration listener : listeners) { + listener.getInstance().schemaSourceEncountered(result); + } + } + + @Override + public void onFailure(final Throwable t) { + LOG.trace("Skipping notification for encountered source {}, fetching source failed", id, t); + } + }); + + return fetchSourceFuture; } private synchronized void addSource(final PotentialSchemaSource source, final AbstractSchemaSourceRegistration reg) { - Multimap, AbstractSchemaSourceRegistration> m = sources.get(source.getSourceIdentifier()); + ListMultimap, AbstractSchemaSourceRegistration> m = sources.get(source.getSourceIdentifier()); if (m == null) { - m = HashMultimap.create(); + m = ArrayListMultimap.create(); sources.put(source.getSourceIdentifier(), m); } @@ -124,21 +151,23 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche } if (m.isEmpty()) { - sources.remove(m); + sources.remove(source.getSourceIdentifier()); } } } @Override public SchemaSourceRegistration registerSchemaSource(final SchemaSourceProvider provider, final PotentialSchemaSource source) { - final AbstractSchemaSourceRegistration ret = new AbstractSchemaSourceRegistration(provider, source) { + final PotentialSchemaSource src = source.cachedReference(); + + final AbstractSchemaSourceRegistration ret = new AbstractSchemaSourceRegistration(provider, src) { @Override protected void removeRegistration() { - removeSource(source, this); + removeSource(src, this); } }; - addSource(source, ret); + addSource(src, ret); return ret; } @@ -166,4 +195,13 @@ public abstract class AbstractSchemaRepository implements SchemaRepository, Sche } return ret; } + + private static class SchemaProviderCostComparator implements Comparator> { + public static final SchemaProviderCostComparator INSTANCE = new SchemaProviderCostComparator(); + + @Override + public int compare(final AbstractSchemaSourceRegistration o1, final AbstractSchemaSourceRegistration o2) { + return o1.getInstance().getCost() - o2.getInstance().getCost(); + } + } }