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

org.apache.jackrabbit.oak.plugins.atomic.AtomicCounterEditorProvider Maven / Gradle / Ivy

There is a newer version: 1.68.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.jackrabbit.oak.plugins.atomic;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.commons.concurrent.ExecutorCloser;
import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
import org.apache.jackrabbit.oak.spi.state.Clusterable;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import static org.osgi.service.component.annotations.ReferenceCardinality.OPTIONAL;
import static org.osgi.service.component.annotations.ReferencePolicy.DYNAMIC;

/**
 * Provide an instance of {@link AtomicCounterEditor}. See {@link AtomicCounterEditor} for
 * behavioural details.
 */
@Component(
        property = "type=atomicCounter",
        service = EditorProvider.class)
public class AtomicCounterEditorProvider implements EditorProvider {
    private static final Logger LOG = LoggerFactory.getLogger(AtomicCounterEditorProvider.class);

    private AtomicReference cluster = new AtomicReference();

    private volatile AtomicReference store = new AtomicReference();    

    private volatile AtomicReference scheduler = new AtomicReference();
    private volatile AtomicReference whiteboard = new AtomicReference();
    
    private final Supplier clusterSupplier;
    private final Supplier schedulerSupplier;
    private final Supplier storeSupplier;
    private final Supplier wbSupplier;
    
    /**
     * OSGi oriented constructor where all the required dependencies will be taken care of.
     */
    public AtomicCounterEditorProvider() {
        clusterSupplier = new Supplier() {
            @Override
            public Clusterable get() {
                return cluster.get();
            }
        };
        schedulerSupplier = new Supplier() {
            @Override
            public ScheduledExecutorService get() {
                return scheduler.get();
            }
        };
        storeSupplier = new Supplier() {
            @Override
            public NodeStore get() {
                return store.get();
            }
        };
        wbSupplier = new Supplier() {
            @Override
            public Whiteboard get() {
                return whiteboard.get();
            }
        };
    }

    /**
     * 

* Plain Java oriented constructor. Refer to * {@link AtomicCounterEditor#AtomicCounterEditor(NodeBuilder, String, ScheduledExecutorService, NodeStore, Whiteboard)} * for constructions details of the actual editor. *

* *

* Based on the use case this may need an already set of the constructor parameters during the * repository construction. Please ensure they're registered before this provider is registered. *

* * @param clusterInfo cluster node information * @param executor the executor for running asynchronously. * @param store reference to the NodeStore. * @param whiteboard the underlying board for picking up the registered {@link CommitHook} */ public AtomicCounterEditorProvider(@Nullable Supplier clusterInfo, @Nullable Supplier executor, @Nullable Supplier store, @Nullable Supplier whiteboard) { this.clusterSupplier = clusterInfo; this.schedulerSupplier = executor; this.storeSupplier = store; this.wbSupplier = whiteboard; } /** * convenience method wrapping logic around {@link AtomicReference} * * @return */ private String getInstanceId() { Clusterable c = clusterSupplier.get(); if (c == null) { return null; } else { return c.getInstanceId(); } } /** * convenience method wrapping logic around {@link AtomicReference} * * @return */ private ScheduledExecutorService getScheduler() { return schedulerSupplier.get(); } /** * convenience method wrapping logic around {@link AtomicReference} * * @return */ private NodeStore getStore() { return storeSupplier.get(); } /** * Convenience method wrapping logic around {@link AtomicReference} * * @return */ private Whiteboard getBoard() { return wbSupplier.get(); } @Activate public void activate(BundleContext context) { whiteboard.set(new OsgiWhiteboard(context)); ThreadFactory tf = new ThreadFactoryBuilder().setNameFormat("atomic-counter-%d").build(); scheduler.set(Executors.newScheduledThreadPool(10, tf)); } @Deactivate public void deactivate() { ScheduledExecutorService ses = getScheduler(); if (ses == null) { LOG.debug("No ScheduledExecutorService found"); } else { LOG.debug("Shutting down ScheduledExecutorService"); new ExecutorCloser(ses).close(); } } @Reference(name = "cluster", policy = DYNAMIC, cardinality = OPTIONAL) protected void bindCluster(Clusterable store) { this.cluster.set(store); } protected void unbindCluster(Clusterable store) { this.cluster.compareAndSet(store, null); } @Reference(name = "store", policy = DYNAMIC, cardinality = OPTIONAL) protected void bindStore(NodeStore store) { this.store.set(store); } protected void unbindStore(NodeStore store) { this.store.compareAndSet(store, null); } @Override public Editor getRootEditor(final NodeState before, final NodeState after, final NodeBuilder builder, final CommitInfo info) throws CommitFailedException { return new AtomicCounterEditor(builder, getInstanceId(), getScheduler(), getStore(), getBoard()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy