All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.container.standalone.StandaloneSubscriberFactory Maven / Gradle / Ivy

There is a newer version: 8.442.54
Show newest version
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.standalone;

import com.yahoo.config.ConfigBuilder;
import com.yahoo.config.ConfigInstance;
import com.yahoo.config.subscription.ConfigInterruptedException;
import com.yahoo.config.subscription.SubscriberClosedException;
import com.yahoo.container.di.config.Subscriber;
import com.yahoo.container.di.config.SubscriberFactory;
import com.yahoo.vespa.config.ConfigKey;
import com.yahoo.vespa.model.VespaModel;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Tony Vaagenes
 * @author gjoranv
 * @author ollivir
 */
public class StandaloneSubscriberFactory implements SubscriberFactory {

    private final VespaModel root;

    public StandaloneSubscriberFactory(VespaModel root) {
        this.root = root;
    }

    private class StandaloneSubscriber implements Subscriber {

        private final Set> configKeys;
        private long generation = -1L;
        private volatile boolean shutdown = false;

        StandaloneSubscriber(Set> configKeys) {
            this.configKeys = configKeys;
        }

        @Override
        public boolean configChanged() {
            return generation == 0;
        }

        @Override public void close() { shutdown = true; }

        @Override
        public Map, ConfigInstance> config() {
            Map, ConfigInstance> ret = new HashMap<>();
            for (ConfigKey key : configKeys) {
                ConfigInstance.Builder builder = root.getConfig(newBuilderInstance(key), key.getConfigId());
                if (builder == null)
                    throw new RuntimeException("Invalid config id " + key.getConfigId());
                ret.put(key, newConfigInstance(builder));
            }
            return ret;
        }

        @Override
        public long waitNextGeneration(boolean isInitializing) {
            generation++;

            if (generation != 0) {
                try {
                    while (!shutdown && !Thread.interrupted()) {
                        Thread.sleep(100);
                    }
                    if (shutdown) throw new SubscriberClosedException();
                } catch (InterruptedException e) {
                    throw new ConfigInterruptedException(e);
                }
            }

            return generation;
        }

        // if waitNextGeneration has not yet been called, -1 should be returned
        @Override
        public long generation() {
            return generation;
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public Subscriber getSubscriber(Set> configKeys, String name) {
        return new StandaloneSubscriber((Set>) configKeys);
    }

    public void reloadActiveSubscribers(long generation) {
        throw new RuntimeException("unsupported");
    }

    private static ConfigInstance.Builder newBuilderInstance(ConfigKey key) {
        try {
            return builderClass(key).getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("ConfigInstance builder cannot be instantiated", e);
        }
    }

    @SuppressWarnings("unchecked")
    private static Class builderClass(ConfigKey key) {
        Class configClass = key.getConfigClass();
        if (configClass != null) {
            Class[] nestedClasses = configClass.getClasses();
            for (Class clazz : nestedClasses) {
                if (clazz.getName().equals(key.getConfigClass().getName() + "$Builder")) {
                    return (Class) clazz;
                }
            }
        }
        throw new RuntimeException("Builder class for " + (configClass == null ? null : configClass.getName()) + " could not be located");
    }

    private static ConfigInstance newConfigInstance(ConfigBuilder builder) {
        try {
            return configClass(builder).getConstructor(builder.getClass()).newInstance(builder);
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("ConfigInstance cannot be instantiated", e);
        }
    }

    @SuppressWarnings("unchecked")
    private static Class configClass(ConfigBuilder builder) {
        return (Class) builder.getClass().getEnclosingClass();
    }
    @Override public void close() {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy