Repository: bookkeeper Updated Branches: refs/heads/master 8324632b2 -> c43858b50
BOOKKEEPER-941: Feature Switches for controling client and server behavior - Introduce Features that are dynamic configuration options - Allow specifying Features as configuration parameters This is a port of the feature switches following changes https://github.com/twitter/bookkeeper/commit/c2a092ab9b585f1d30d9e9b9dead0533efa49855 https://github.com/twitter/bookkeeper/commit/f9762d126e311a6b129e6e169dc62c2a0bdb7b4a Author: Robin Dhamankar <[email protected]> Reviewers: Matteo Merli <[email protected]>, Sijie Guo <[email protected]> Closes #54 from robindh/FeatureSwitches Project: http://git-wip-us.apache.org/repos/asf/bookkeeper/repo Commit: http://git-wip-us.apache.org/repos/asf/bookkeeper/commit/c43858b5 Tree: http://git-wip-us.apache.org/repos/asf/bookkeeper/tree/c43858b5 Diff: http://git-wip-us.apache.org/repos/asf/bookkeeper/diff/c43858b5 Branch: refs/heads/master Commit: c43858b5095318b50f4c7f86fc33b0a9e454bee5 Parents: 8324632 Author: Robin Dhamankar <[email protected]> Authored: Sat Jul 30 22:56:28 2016 -0700 Committer: Sijie Guo <[email protected]> Committed: Sat Jul 30 22:56:28 2016 -0700 ---------------------------------------------------------------------- .../bookkeeper/conf/AbstractConfiguration.java | 13 +++ .../feature/CacheableFeatureProvider.java | 85 ++++++++++++++++++++ .../org/apache/bookkeeper/feature/Feature.java | 51 ++++++++++++ .../bookkeeper/feature/FeatureProvider.java | 44 ++++++++++ .../bookkeeper/feature/FixedValueFeature.java | 52 ++++++++++++ .../bookkeeper/feature/SettableFeature.java | 41 ++++++++++ .../feature/SettableFeatureProvider.java | 48 +++++++++++ 7 files changed, 334 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java index 314290e..adf08ff 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java @@ -25,6 +25,7 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.SystemConfiguration; +import org.apache.bookkeeper.feature.Feature; import org.apache.bookkeeper.meta.LedgerManagerFactory; import org.apache.bookkeeper.util.ReflectionUtils; @@ -243,4 +244,16 @@ public abstract class AbstractConfiguration extends CompositeConfiguration { public void setMetastoreMaxEntriesPerScan(int maxEntries) { setProperty(METASTORE_MAX_ENTRIES_PER_SCAN, maxEntries); } + + public void setFeature(String configProperty, Feature feature) { + setProperty(configProperty, feature); + } + + public Feature getFeature(String configProperty, Feature defaultValue) { + if (null == getProperty(configProperty)) { + return defaultValue; + } else { + return (Feature)getProperty(configProperty); + } + } } http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/CacheableFeatureProvider.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/CacheableFeatureProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/CacheableFeatureProvider.java new file mode 100644 index 0000000..95c9981 --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/CacheableFeatureProvider.java @@ -0,0 +1,85 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +import org.apache.commons.lang.StringUtils; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Cacheable Feature Provider + */ +public abstract class CacheableFeatureProvider<T extends Feature> implements FeatureProvider { + + protected final String scope; + protected final ConcurrentMap<String, FeatureProvider> scopes = + new ConcurrentHashMap<String, FeatureProvider>(); + protected final ConcurrentMap<String, T> features = + new ConcurrentHashMap<String, T>(); + + protected CacheableFeatureProvider(String scope) { + this.scope = scope; + } + + protected String makeName(String name) { + if (StringUtils.isBlank(scope)) { + return name; + } else { + return scope + "." + name; + } + } + + @Override + public T getFeature(String name) { + T feature = features.get(name); + if (null == feature) { + T newFeature = makeFeature(makeName(name)); + T oldFeature = features.putIfAbsent(name, newFeature); + if (null == oldFeature) { + feature = newFeature; + } else { + feature = oldFeature; + } + } + return feature; + } + + protected abstract T makeFeature(String featureName); + + @Override + public FeatureProvider scope(String name) { + FeatureProvider provider = scopes.get(name); + if (null == provider) { + FeatureProvider newProvider = makeProvider(makeName(name)); + FeatureProvider oldProvider = scopes.putIfAbsent(name, newProvider); + if (null == oldProvider) { + provider = newProvider; + } else { + provider = oldProvider; + } + } + return provider; + } + + protected abstract FeatureProvider makeProvider(String fullScopeName); +} http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/Feature.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/Feature.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/Feature.java new file mode 100644 index 0000000..ab9fae9 --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/Feature.java @@ -0,0 +1,51 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +/** + * This interface represents a feature. + */ +public interface Feature { + public static int FEATURE_AVAILABILITY_MAX_VALUE = 100; + + /** + * Returns a textual representation of the feature. + * + * @return name of the feature. + */ + String name(); + + /** + * Returns the availability of this feature, an integer between 0 and 100. + * + * @return the availability of this feature. + */ + int availability(); + + /** + * Whether this feature is available or not. + * + * @return true if this feature is available, otherwise false. + */ + boolean isAvailable(); +} + http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FeatureProvider.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FeatureProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FeatureProvider.java new file mode 100644 index 0000000..04686b7 --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FeatureProvider.java @@ -0,0 +1,44 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +/** + * Provider to provide features. + */ +public interface FeatureProvider { + /** + * Return the feature with given name. + * + * @param name feature name + * @return feature instance + */ + Feature getFeature(String name); + + /** + * Provide the feature provider under scope <i>name</i>. + * + * @param name + * scope name. + * @return feature provider under scope <i>name</i> + */ + FeatureProvider scope(String name); +} http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FixedValueFeature.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FixedValueFeature.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FixedValueFeature.java new file mode 100644 index 0000000..825276b --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/FixedValueFeature.java @@ -0,0 +1,52 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +public class FixedValueFeature implements Feature { + protected final String name; + protected int availability; + + public FixedValueFeature(String name, int availability) { + this.name = name; + this.availability = availability; + } + + public FixedValueFeature(String name, boolean available) { + this.name = name; + this.availability = available ? FEATURE_AVAILABILITY_MAX_VALUE : 0; + } + + @Override + public String name() { + return null; + } + + @Override + public int availability() { + return availability; + } + + @Override + public boolean isAvailable() { + return availability() > 0; + } +} http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeature.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeature.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeature.java new file mode 100644 index 0000000..f175bf0 --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeature.java @@ -0,0 +1,41 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +public class SettableFeature extends FixedValueFeature { + public SettableFeature(String name, int initialAvailability) { + super(name, initialAvailability); + } + + public SettableFeature(String name, boolean isAvailabile) { + super(name, isAvailabile); + } + + public void set(int availability) { + this.availability = availability; + } + + public void set(boolean isAvailabile) { + this.availability = isAvailabile ? FEATURE_AVAILABILITY_MAX_VALUE : 0; + } + +} http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/c43858b5/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeatureProvider.java ---------------------------------------------------------------------- diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeatureProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeatureProvider.java new file mode 100644 index 0000000..e21ad9d --- /dev/null +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/feature/SettableFeatureProvider.java @@ -0,0 +1,48 @@ +package org.apache.bookkeeper.feature; + +/* + * + * 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. + * + */ + +/** + * A provider will provide settable features. + */ +public class SettableFeatureProvider extends CacheableFeatureProvider<SettableFeature> { + + public final static FeatureProvider DISABLE_ALL = new SettableFeatureProvider("", 0); + + protected final int availability; + + public SettableFeatureProvider(String scope, int availability) { + super(scope); + this.availability = availability; + } + + @Override + protected SettableFeature makeFeature(String featureName) { + return new SettableFeature(featureName, availability); + } + + @Override + protected FeatureProvider makeProvider(String fullScopeName) { + return new SettableFeatureProvider(fullScopeName, availability); + } + +}
