blob: a9ea839b3a6a77fd0e83c5a1a23186ab20207606 [file] [log] [blame]
/*
* 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.spi.whiteboard;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.jackrabbit.oak.commons.jmx.JmxUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.ScheduleExecutionInstanceTypes.DEFAULT;
import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.ScheduleExecutionInstanceTypes.RUN_ON_LEADER;
import static org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.ScheduleExecutionInstanceTypes.RUN_ON_SINGLE;
public class WhiteboardUtils {
/**
* JMX Domain name under which Oak related JMX MBeans are registered
*/
public static final String JMX_OAK_DOMAIN = "org.apache.jackrabbit.oak";
public enum ScheduleExecutionInstanceTypes {
DEFAULT,
RUN_ON_SINGLE,
RUN_ON_LEADER
}
public static Registration scheduleWithFixedDelay(
Whiteboard whiteboard, Runnable runnable, long delayInSeconds) {
return scheduleWithFixedDelay(whiteboard, runnable, delayInSeconds, false, false);
}
public static Registration scheduleWithFixedDelay(
Whiteboard whiteboard, Runnable runnable, long delayInSeconds, boolean runOnSingleClusterNode,
boolean useDedicatedPool) {
return scheduleWithFixedDelay(whiteboard, runnable, Collections.<String, Object>emptyMap(),
delayInSeconds, runOnSingleClusterNode, useDedicatedPool);
}
public static Registration scheduleWithFixedDelay(
Whiteboard whiteboard, Runnable runnable, Map<String, Object> extraProps, long delayInSeconds, boolean runOnSingleClusterNode,
boolean useDedicatedPool) {
return scheduleWithFixedDelay(whiteboard, runnable, extraProps, delayInSeconds,
runOnSingleClusterNode ? RUN_ON_SINGLE : DEFAULT,
useDedicatedPool);
}
public static Registration scheduleWithFixedDelay(
Whiteboard whiteboard, Runnable runnable, Map<String, Object> extraProps, long delayInSeconds,
ScheduleExecutionInstanceTypes scheduleExecutionInstanceTypes, boolean useDedicatedPool) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
.putAll(extraProps)
.put("scheduler.period", delayInSeconds)
.put("scheduler.concurrent", false);
if (scheduleExecutionInstanceTypes == RUN_ON_SINGLE) {
//Make use of feature while running in Sling SLING-5387
builder.put("scheduler.runOn", "SINGLE");
} else if (scheduleExecutionInstanceTypes == RUN_ON_LEADER) {
//Make use of feature while running in Sling SLING-2979
builder.put("scheduler.runOn", "LEADER");
}
if (useDedicatedPool) {
//Make use of dedicated threadpool SLING-5831
builder.put("scheduler.threadPool", "oak");
}
return whiteboard.register(
Runnable.class, runnable, builder.build());
}
public static <T> Registration registerMBean(
Whiteboard whiteboard,
Class<T> iface, T bean, String type, String name) {
return registerMBean(whiteboard, iface, bean, type, name, Collections.<String, String>emptyMap());
}
public static <T> Registration registerMBean(
Whiteboard whiteboard,
Class<T> iface, T bean, String type, String name, Map<String, String> attrs) {
try {
Hashtable<String, String> table = new Hashtable<String, String>(attrs);
table.put("type", JmxUtil.quoteValueIfRequired(type));
table.put("name", JmxUtil.quoteValueIfRequired(name));
ImmutableMap.Builder properties = ImmutableMap.builder();
properties.put("jmx.objectname", new ObjectName(JMX_OAK_DOMAIN, table));
properties.putAll(attrs);
return whiteboard.register(iface, bean, properties.build());
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Returns the currently available services from the whiteboard of the tracked type.
*
* Note that the underlying tracker is closed automatically.
*
* @param wb the whiteboard
* @param type the service type
* @return a list of services
*/
@NotNull
public static <T> List<T> getServices(@NotNull Whiteboard wb, @NotNull Class<T> type) {
return getServices(wb, type, null);
}
/**
* Returns the one of the currently available services from the whiteboard of the tracked type.
*
* Note that the underlying tracker is closed automatically.
*
* @return one service or {@code null}
*/
@Nullable
public static <T> T getService(@NotNull Whiteboard wb, @NotNull Class<T> type) {
return getService(wb, type, null);
}
/**
* Returns the currently available services from the whiteboard of the tracked type. If {@code predicate} is
* not {@code null} the returned list is limited to the ones that match the predicate.
*
* Note that the underlying tracker is stopped automatically after the services are returned.
*
* @param wb the whiteboard
* @param type the service type
* @param predicate filtering predicate or {@code null}
* @return a list of services
*/
@NotNull
public static <T> List<T> getServices(@NotNull Whiteboard wb, @NotNull Class<T> type, @Nullable Predicate<T> predicate) {
Tracker<T> tracker = wb.track(type);
try {
if (predicate == null) {
return tracker.getServices();
} else {
return ImmutableList.copyOf(Iterables.filter(tracker.getServices(), predicate));
}
} finally {
tracker.stop();
}
}
/**
* Returns the one of the currently available services from the whiteboard of the tracked type. If {@code predicate} is
* not {@code null} only a service that match the predicate is returned.
*
* Note that the underlying tracker is closed automatically.
*
* @param wb the whiteboard
* @param type the service type
* @param predicate filtering predicate or {@code null}
* @return one service or {@code null}
*/
@Nullable
public static <T> T getService(@NotNull Whiteboard wb, @NotNull Class<T> type, @Nullable Predicate<T> predicate) {
Tracker<T> tracker = wb.track(type);
try {
for (T service : tracker.getServices()) {
if (predicate == null || predicate.apply(service)) {
return service;
}
}
return null;
} finally {
tracker.stop();
}
}
}