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

org.wildfly.discovery.impl.LocalRegistryAndDiscoveryProvider Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2016 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wildfly.discovery.impl;

import static java.lang.Math.max;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import org.wildfly.common.Assert;
import org.wildfly.discovery.AggregateServiceRegistration;
import org.wildfly.discovery.FilterSpec;
import org.wildfly.discovery.ServiceRegistration;
import org.wildfly.discovery.ServiceType;
import org.wildfly.discovery.ServiceURL;
import org.wildfly.discovery.spi.DiscoveryProvider;
import org.wildfly.discovery.spi.DiscoveryRequest;
import org.wildfly.discovery.spi.DiscoveryResult;
import org.wildfly.discovery.spi.RegistryProvider;

/**
 * A local in-memory service registry and discovery provider.  Services registered with this provider can be subsequently
 * discovered.  Since all operations happen in-memory, the discovery provider always completes immediately.
 *
 * @author David M. Lloyd
 */
public final class LocalRegistryAndDiscoveryProvider implements RegistryProvider, DiscoveryProvider {
    private final CopyOnWriteArrayList handles = new CopyOnWriteArrayList<>();

    public ServiceRegistration registerService(final ServiceURL serviceURL) {
        Assert.checkNotNullParam("serviceURL", serviceURL);
        final Handle handle = new Handle(serviceURL, true);
        handles.add(handle);
        return handle;
    }

    public ServiceRegistration registerServices(final ServiceURL... serviceURLs) {
        Assert.checkNotNullParam("serviceURLs", serviceURLs);
        Handle[] array = new Handle[serviceURLs.length];
        for (int i = 0; i < serviceURLs.length; i++) {
            final ServiceURL serviceURL = serviceURLs[i];
            array[i] = new Handle(serviceURL, false);
        }
        final List list = Arrays.asList(array);
        handles.addAll(list);
        return new AggregateHandle(list, array);
    }

    public DiscoveryRequest discover(final ServiceType serviceType, final FilterSpec filterSpec, final DiscoveryResult result) {
        ServiceURL serviceURL;
        for (Handle handle : handles) {
            if (! handle.isOpenAndActive()) {
                continue;
            }
            serviceURL = handle.getServiceURL();
            if (serviceType.implies(serviceURL) && serviceURL.satisfies(filterSpec)) {
                result.addMatch(serviceURL);
            }
        }
        result.complete();
        return DiscoveryRequest.NULL;
    }

    private static final long stamp = System.nanoTime();

    static long nowMicros() {
        return max(0L, (System.nanoTime() - stamp >>> 1) / 500L);
    }

    final class AggregateHandle extends AggregateServiceRegistration {
        private final List registrations;

        AggregateHandle(final List asList, final Handle... registrations) {
            super((ServiceRegistration[]) registrations);
            this.registrations = asList;
        }

        public void close() {
            // remove far more efficiently
            handles.removeAll(this.registrations);
            super.close();
        }
    }

    final class Handle implements ServiceRegistration {
        @SuppressWarnings("NumericOverflow")
        private static final int FLAG_CLOSED       = 1 << 0;
        private static final int FLAG_DEACTIVATED  = 1 << 1;

        private final AtomicInteger state = new AtomicInteger(0);
        private final ServiceURL serviceURL;
        private final boolean remove;

        Handle(final ServiceURL serviceURL, final boolean remove) {
            this.serviceURL = serviceURL;
            this.remove = remove;
        }

        public void close() {
            if (remove) handles.remove(this);
            state.set(FLAG_CLOSED);
        }

        public void deactivate() {
            final AtomicInteger state = this.state;
            int oldVal;
            do {
                oldVal = state.get();
                if ((oldVal & (FLAG_CLOSED | FLAG_DEACTIVATED)) != 0L) {
                    // nothing to do
                    return;
                }
            } while (! state.compareAndSet(oldVal, FLAG_DEACTIVATED));
        }

        public void activate() {
            final AtomicInteger state = this.state;
            int oldVal;
            do {
                oldVal = state.get();
                if ((oldVal & FLAG_CLOSED) != 0) {
                    // nothing to do
                    return;
                }
                if (oldVal == 0) {
                    // already active
                    return;
                }
            } while (! state.compareAndSet(oldVal, 0));
        }

        ServiceURL getServiceURL() {
            return serviceURL;
        }

        boolean isOpenAndActive() {
            final long val = state.get();
            return (val & (FLAG_CLOSED | FLAG_DEACTIVATED)) == 0L;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy