You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by st...@apache.org on 2021/09/14 12:26:17 UTC
[jackrabbit-oak] branch trunk updated: OAK-9568 : Support custom
osgi LeaseFailureHandler (#364)
This is an automated email from the ASF dual-hosted git repository.
stefanegli pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new 3446052 OAK-9568 : Support custom osgi LeaseFailureHandler (#364)
3446052 is described below
commit 3446052ad5f3316d75d4f05cc75e523dde9a1afd
Author: stefan-egli <st...@apache.org>
AuthorDate: Tue Sep 14 14:26:09 2021 +0200
OAK-9568 : Support custom osgi LeaseFailureHandler (#364)
* OAK-9535 related : trying to increase mvn memory
* OAK-9568 : Support custom osgi LeaseFailureHandler
* releng : avoid pushing Jenkinsfile changes
* OAK-9568 : custom LeaseFailureHandler support test added
* OAK-9568 : fixing failing test setups
* OAK-9568 : moved LeaseFailureHandler to dedicated, exported, versioned package
* OAK-9568 : LeaseFailureHandler added to bundle's Export-Package, plus IT added
---
.../org/apache/jackrabbit/oak/osgi/OSGiIT.java | 12 ++++
oak-store-document/pom.xml | 1 +
.../oak/plugins/document/ClusterNodeInfo.java | 5 ++
.../plugins/document/DocumentNodeStoreBuilder.java | 1 +
.../plugins/document/DocumentNodeStoreService.java | 64 +++++++++++++++++-----
.../{ => spi/lease}/LeaseFailureHandler.java | 2 +-
.../plugins/document/spi/lease/package-info.java | 28 ++++++++++
.../oak/plugins/document/ClusterNodeInfoTest.java | 1 +
.../document/DocumentNodeStoreServiceTest.java | 50 +++++++++++++++++
.../document/mongo/LeaseUpdateSocketTimeoutIT.java | 2 +-
10 files changed, 150 insertions(+), 16 deletions(-)
diff --git a/oak-it-osgi/src/test/java/org/apache/jackrabbit/oak/osgi/OSGiIT.java b/oak-it-osgi/src/test/java/org/apache/jackrabbit/oak/osgi/OSGiIT.java
index c5d8e45..896b43e 100644
--- a/oak-it-osgi/src/test/java/org/apache/jackrabbit/oak/osgi/OSGiIT.java
+++ b/oak-it-osgi/src/test/java/org/apache/jackrabbit/oak/osgi/OSGiIT.java
@@ -34,6 +34,7 @@ import javax.inject.Inject;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -151,4 +152,15 @@ public class OSGiIT {
System.out.println(repository.getDescriptor(Repository.REP_NAME_DESC));
}
+ @Test
+ public void testLeaseFailureHandlerIsExported() {
+ LeaseFailureHandler handler = new LeaseFailureHandler() {
+ @Override
+ public void handleLeaseFailure() {
+ // this empty block is okay
+ }
+ };
+ context.registerService("org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler",
+ handler, null);
+ }
}
diff --git a/oak-store-document/pom.xml b/oak-store-document/pom.xml
index d1d7238..0868820 100644
--- a/oak-store-document/pom.xml
+++ b/oak-store-document/pom.xml
@@ -50,6 +50,7 @@
</Import-Package>
<Export-Package>
org.apache.jackrabbit.oak.plugins.document.spi,
+ org.apache.jackrabbit.oak.plugins.document.spi.lease
</Export-Package>
<Embed-Dependency>quartz;inline=org/quartz/CronExpression*|org/quartz/ValueSet*</Embed-Dependency>
</instructions>
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
index eca976c..02679d2 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
@@ -43,6 +43,7 @@ import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
import org.apache.jackrabbit.oak.commons.StringUtils;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.plugins.document.util.SystemPropertySupplier;
import org.apache.jackrabbit.oak.stats.Clock;
import org.jetbrains.annotations.NotNull;
@@ -1120,6 +1121,10 @@ public class ClusterNodeInfo {
return leaseEndTime;
}
+ LeaseFailureHandler getLeaseFailureHandler() {
+ return leaseFailureHandler;
+ }
+
public void setLeaseFailureHandler(LeaseFailureHandler leaseFailureHandler) {
this.leaseFailureHandler = leaseFailureHandler;
}
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBuilder.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBuilder.java
index 7987dc8..8ada1f4 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBuilder.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBuilder.java
@@ -48,6 +48,7 @@ import org.apache.jackrabbit.oak.plugins.document.persistentCache.CacheType;
import org.apache.jackrabbit.oak.plugins.document.persistentCache.EvictionListener;
import org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCache;
import org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCacheStats;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.plugins.document.util.RevisionsKey;
import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
import org.apache.jackrabbit.oak.spi.blob.AbstractBlobStore;
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
index 1c36fc2..758c0ab 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
@@ -39,6 +39,7 @@ import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -66,6 +67,7 @@ import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentNodeStoreBu
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStoreMetrics;
import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentNodeStoreBuilder;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.spi.commit.ObserverTracker;
import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
@@ -97,6 +99,7 @@ import org.apache.jackrabbit.oak.spi.state.RevisionGC;
import org.apache.jackrabbit.oak.spi.state.RevisionGCMBean;
import org.apache.jackrabbit.oak.spi.whiteboard.AbstractServiceTracker;
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Tracker;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardExecutor;
import org.apache.jackrabbit.oak.stats.StatisticsProvider;
@@ -402,9 +405,34 @@ public class DocumentNodeStoreService {
nodeStore, props);
}
+ private LeaseFailureHandler createDefaultLeaseFailureHandler() {
+ return new LeaseFailureHandler() {
+ @Override
+ public void handleLeaseFailure() {
+ Bundle bundle = context.getBundleContext().getBundle();
+ String bundleName = bundle.getSymbolicName();
+ try {
+ // plan A: try stopping oak-store-document
+ log.error("handleLeaseFailure: stopping {}...", bundleName);
+ bundle.stop(Bundle.STOP_TRANSIENT);
+ log.error("handleLeaseFailure: stopped {}.", bundleName);
+ // plan A worked, perfect!
+ } catch (BundleException e) {
+ log.error("handleLeaseFailure: exception while stopping " + bundleName + ": " + e, e);
+ // plan B: stop only DocumentNodeStoreService (to stop the background threads)
+ log.error("handleLeaseFailure: stopping DocumentNodeStoreService...");
+ context.disableComponent(DocumentNodeStoreService.class.getName());
+ log.error("handleLeaseFailure: stopped DocumentNodeStoreService");
+ // plan B succeeded.
+ }
+ }
+ };
+ }
+
private void configureBuilder(DocumentNodeStoreBuilder<?> builder) {
String persistentCache = resolvePath(config.persistentCache(), DEFAULT_PERSISTENT_CACHE);
String journalCache = resolvePath(config.journalCache(), DEFAULT_JOURNAL_CACHE);
+ final Tracker<LeaseFailureHandler> leaseFailureHandlerTracker = whiteboard.track(LeaseFailureHandler.class);
builder.setStatisticsProvider(statisticsProvider).
setExecutor(executor).
memoryCacheSize(config.cache() * MB).
@@ -420,23 +448,31 @@ public class DocumentNodeStoreService {
setLeaseCheckMode(ClusterNodeInfo.DEFAULT_LEASE_CHECK_DISABLED ? LeaseCheckMode.DISABLED : LeaseCheckMode.valueOf(config.leaseCheckMode())).
setLeaseFailureHandler(new LeaseFailureHandler() {
+ private final LeaseFailureHandler defaultLeaseFailureHandler = createDefaultLeaseFailureHandler();
+
@Override
public void handleLeaseFailure() {
- Bundle bundle = context.getBundleContext().getBundle();
- String bundleName = bundle.getSymbolicName();
+ boolean handled = false;
try {
- // plan A: try stopping oak-store-document
- log.error("handleLeaseFailure: stopping {}...", bundleName);
- bundle.stop(Bundle.STOP_TRANSIENT);
- log.error("handleLeaseFailure: stopped {}.", bundleName);
- // plan A worked, perfect!
- } catch (BundleException e) {
- log.error("handleLeaseFailure: exception while stopping " + bundleName + ": " + e, e);
- // plan B: stop only DocumentNodeStoreService (to stop the background threads)
- log.error("handleLeaseFailure: stopping DocumentNodeStoreService...");
- context.disableComponent(DocumentNodeStoreService.class.getName());
- log.error("handleLeaseFailure: stopped DocumentNodeStoreService");
- // plan B succeeded.
+ if (leaseFailureHandlerTracker != null) {
+ final List<LeaseFailureHandler> handlers = leaseFailureHandlerTracker.getServices();
+ if (handlers != null && handlers.size() > 0) {
+ // go through the list, but only execute the first one
+ for (LeaseFailureHandler handler : handlers) {
+ if (handler != null) {
+ log.info("handleLeaseFailure: invoking handler " + handler);
+ handler.handleLeaseFailure();
+ handled = true;
+ break;
+ }
+ }
+ }
+ }
+ } finally {
+ if (!handled) {
+ log.info("handleLeaseFailure: invoking default handler");
+ defaultLeaseFailureHandler.handleLeaseFailure();
+ }
}
}
}).
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LeaseFailureHandler.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/LeaseFailureHandler.java
similarity index 96%
rename from oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LeaseFailureHandler.java
rename to oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/LeaseFailureHandler.java
index b348845..8f2b36e 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LeaseFailureHandler.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/LeaseFailureHandler.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.plugins.document;
+package org.apache.jackrabbit.oak.plugins.document.spi.lease;
/**
* A LeaseFailureHandler can be provided to the DocumentMK.Builder
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/package-info.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/package-info.java
new file mode 100644
index 0000000..d6a9a4e
--- /dev/null
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/spi/lease/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provides extensibility with regards to DocumentNodeStore leases.
+ *
+ * @version 1.0.0
+ */
+@Version("1.0.0")
+package org.apache.jackrabbit.oak.plugins.document.spi.lease;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
index cfba4d9..0f3ed5f 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
@@ -30,6 +30,7 @@ import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.stats.Clock;
import org.junit.After;
import org.junit.Before;
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java
index 999659b..2292ff0 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreServiceTest.java
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.plugins.document;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import com.google.common.collect.Maps;
@@ -28,6 +29,7 @@ import org.apache.commons.io.FilenameUtils;
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStoreTestHelper;
import org.apache.jackrabbit.oak.plugins.document.spi.JournalPropertyService;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.stats.StatisticsProvider;
import org.apache.sling.testing.mock.osgi.MockOsgi;
@@ -260,6 +262,54 @@ public class DocumentNodeStoreServiceTest {
}
@Test
+ public void defaultLeaseFailureHandlerCheck() {
+ Map<String, Object> config = newConfig(repoHome);
+ MockOsgi.setConfigForPid(context.bundleContext(), PID, config);
+ MockOsgi.activate(service, context.bundleContext());
+ DocumentNodeStore dns = context.getService(DocumentNodeStore.class);
+ assertNotNull(dns);
+ ClusterNodeInfo clusterInfo = dns.getClusterInfo();
+ LeaseFailureHandler leaseFailureHandler = clusterInfo.getLeaseFailureHandler();
+ assertNotNull(leaseFailureHandler);
+ try {
+ leaseFailureHandler.handleLeaseFailure();
+ fail("default leaseFailureHandler should call bundle.stop(), which is not supported");
+ } catch (UnsupportedOperationException u) {
+ // the default LeaseFailureHandler should fail, as it calls bundle.stop()
+ // and that is not supported (throws UnsupportedOperationExceptino)
+ }
+ }
+
+ @Test
+ public void customLeaseFailureHandlerCheck() {
+ final AtomicInteger counter = new AtomicInteger(0);
+ LeaseFailureHandler customLeaseFailureHandler = new LeaseFailureHandler() {
+ @Override
+ public void handleLeaseFailure() {
+ counter.incrementAndGet();
+ }
+ };
+ context.registerService(LeaseFailureHandler.class, customLeaseFailureHandler);
+ Map<String, Object> config = newConfig(repoHome);
+ MockOsgi.setConfigForPid(context.bundleContext(), PID, config);
+ MockOsgi.activate(service, context.bundleContext());
+ DocumentNodeStore dns = context.getService(DocumentNodeStore.class);
+ assertNotNull(dns);
+ ClusterNodeInfo clusterInfo = dns.getClusterInfo();
+ LeaseFailureHandler leaseFailureHandler = clusterInfo.getLeaseFailureHandler();
+ assertNotNull(leaseFailureHandler);
+ assertEquals(0, counter.get());
+ for(int i = 0; i < 10; i++) {
+ // now the custom LeaseFailureHandler should be used,
+ // which just increments a counter.
+ // but more importantly: it should no longer fail,
+ // as does the default LeaseFailureHandler
+ leaseFailureHandler.handleLeaseFailure();
+ assertEquals(i + 1, counter.get());
+ }
+ }
+
+ @Test
public void revisionGcDelayFactorCheckMode() {
Map<String, Object> config = newConfig(repoHome);
double delayFactor = 0.25;
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/LeaseUpdateSocketTimeoutIT.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/LeaseUpdateSocketTimeoutIT.java
index 3c61b1a..83f3b97 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/LeaseUpdateSocketTimeoutIT.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/LeaseUpdateSocketTimeoutIT.java
@@ -26,9 +26,9 @@ import org.apache.jackrabbit.oak.commons.CIHelper;
import org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo;
import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
import org.apache.jackrabbit.oak.plugins.document.DocumentStoreException;
-import org.apache.jackrabbit.oak.plugins.document.LeaseFailureHandler;
import org.apache.jackrabbit.oak.plugins.document.SimpleRecoveryHandler;
import org.apache.jackrabbit.oak.plugins.document.TestUtils;
+import org.apache.jackrabbit.oak.plugins.document.spi.lease.LeaseFailureHandler;
import org.apache.jackrabbit.oak.stats.Clock;
import org.junit.After;
import org.junit.Before;