Try to keep a reference to the segmentStore if you're using that
backend. Eg, we do
// keep references to these
private Repository oakRepository = null;
private SegmentStore segmentStore = null;
// on webapp init
segmentStore = new FileStore(new File(oakRepositoryPath), 256);
NodeStore nodeStore = new SegmentNodeStore(segmentStore); // don't
keep the reference to the nodeStore
oakRepository = new Jcr(nodeStore).with(new LocalInitialContent())
.withAsyncIndexing()
.createRepository();
// on shutdown
if (oakRepository != null) {
((RepositoryImpl)oakRepository).shutdown();
oakRepository = null;
}
if (segmentStore != null) {
segmentStore.close();
}
There's still an unresolved bug that will give you exception on webapp
restart under tomcat, like
22-Jun-2015 16:59:51.228 WARNING [http-nio-8080-exec-143]
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads
The web application [xx] appears to have started a thread named
[oak-scheduled-executor-37] but has failed to stop it. This is very
likely to create a memory leak. Stack trace of thread:
https://issues.apache.org/jira/browse/OAK-2736
On 22 June 2015 at 01:49, Frederic Gilbart <[email protected]> wrote:
> Hi all,
>
> I try to close all Oak resources when my webapp stops using a @PreDestroy.
>
> I either use a DocumentNodeStore or a SegmentNodeStore for the application,
> and I keep a reference using NodeStore.
>
> For DocumentNodeStore I believe the .dispose() is right.
>
> On the opposite SegmentNodeStore does not offer such a dispose() (nor a
> .getBlobStore() as the DocumentNodeStore does which seems handy).
> So I also keep another reference on the underlying BlobStore which requires a
> cast to implementation to be closed : DataStore interface offers the .close()
> but BlobStore doesn't, so I can't close any AbstractBlobStore,
> FileBlobStore; etc...
>
>
> When I stop webapp using Tomcat8 manager (Stop/Start), then start it I find
> following log :
>
> Caused by: java.io.IOException: Could not remove broken tar file C:
> \DEV\repository\oak\data00021a.tar
> at
> org.apache.jackrabbit.oak.plugins.segment.file.TarReader.backupSafely(TarReader.java:179)
> ~[oak-core-1.2.2.jar:1.2.2]
> at
> org.apache.jackrabbit.oak.plugins.segment.file.TarReader.open(TarReader.java:132)
> ~[oak-core-1.2.2.jar:1.2.2]
> at
> org.apache.jackrabbit.oak.plugins.segment.file.FileStore.<init>(FileStore.java:359)
> ~[oak-core-1.2.2.jar:1.2.2]
> at
> org.apache.jackrabbit.oak.plugins.segment.file.FileStore.<init>(FileStore.java:82)
> ~[oak-core-1.2.2.jar:1.2.2]
> at
> org.apache.jackrabbit.oak.plugins.segment.file.FileStore$Builder.create(FileStore.java:292)
> ~[oak-core-1.2.2.jar:1.2.2]
> at
> fr.capsiel.startup.config.OakConfiguration.getRepository(OakConfiguration.java:60)
> ~[aladin-oak-3.0.0-SNAPSHOT.jar:na
> ]
> at
> fr.capsiel.startup.config.OakConfiguration$$EnhancerBySpringCGLIB$$ca54aa3d.CGLIB$getRepository$0(<generated>)
> ~[spri
> ng-core-4.0.9.RELEASE.jar:na]
> at
> fr.capsiel.startup.config.OakConfiguration$$EnhancerBySpringCGLIB$$ca54aa3d$$FastClassBySpringCGLIB$$e557a109.invoke(
> <generated>) ~[spring-core-4.0.9.RELEASE.jar:na]
> at
> org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
> ~[spring-core-4.0.9.RELEASE.jar:4.0.9.RELEASE]
>
> at
> org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer
> .java:311) ~[spring-context-4.0.9.RELEASE.jar:4.0.9.RELEASE]
> at
> fr.capsiel.aladin.startup.config.OakConfiguration$$EnhancerBySpringCGLIB$$ca54aa3d.getRepository(<generated>)
> ~[spring-core-
> 4.0.9.RELEASE.jar:na]
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> ~[na:1.8.0_25]
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> ~[na:1.8.0_25]
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> ~[na:1.8.0_25]
> at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
> at
> org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
> ~[sp
>
>
> The webapp will never start due to mandatory @Autowired Repository bean.
> Note : A full JVM restart (catalina restart) is fine: tar is managed, file
> seems not lost, and webapp starts.
>
>
> I could once again use another reference on SegmentStore wich offers .close()
> or DocumentStore gives .dispose(), but no common interface exists. I could
> keep 2 references for sure.
>
> Question is: am I wrong when I want to use either a Segment or a Document
> Node Storage regarding local or distributed live target? Or am I using wrong
> API level to manage both Storages, at least for shutdown?
> Subsidiary question: what is recommended solution to gracefully close &
> release Oak's resources on shutdown?
> ((RepositoryImpl)this.repository).shutdown(); does not help.
>
>
> From compiler's point of view:
>
> @PreDestroy
> void detroyTest() {
> // No common interface between SegmentStore & DocumentStore
> Object o = null;
> if (o instanceof SegmentStore) {
> ((SegmentStore) o).close();
> } else if (o instanceof DocumentStore) {
> ((DocumentStore) o).dispose();
> }
> NodeStore nodeStore = null;
> if (nodeStore instanceof DocumentNodeStore) {
> ((DocumentNodeStore) nodeStore).dispose(); // ok
> ((DocumentNodeStore)
> nodeStore).getDocumentStore();//useful, but lack corresponding getSegmentStore
> ((DocumentNodeStore)
> this.nodeStore).getBlobStore().close(); // No close on NodeStore, could avoid
> me to keep ref on it
> } else if (nodeStore instanceof SegmentNodeStore) {
> ((SegmentNodeStore) nodeStore).getSegmentStore(); //
> no .getSegmentStore()
> ((SegmentNodeStore) nodeStore).getBlobStore(); // no
> .getBlobStore()
> }
> BlobStore blobStore = null;
> if (blobStore instanceof DataStore) {
> ((DataStore) o).close();
> } else if (blobStore instanceof DataStoreBlobStore) {
> ((DataStoreBlobStore) o).close();
> } else if (blobStore instanceof FileBlobStore) {
> ((FileBlobStore) o).close();// no method
> }
> }
>
> Regards,
> Fred
>
>
--
-Tor