From 4c894a181a8add9480c6a0417855e86293d4d44e Mon Sep 17 00:00:00 2001 From: MishaDemianenko Date: Tue, 24 Jan 2017 17:55:15 +0100 Subject: [PATCH] Start and stop store watcher when replace database store Store often can be replaced in clustering environment when store get copied from another machine and then original database store get replaced. If we will nto gonna stop watcher we will get useless notifications that store files where deleted. --- .../watcher/RestartableFileSystemWatcher.java | 114 ++++++++++++++++++ .../RestartableFileSystemWatcherTest.java | 92 ++++++++++++++ .../kernel/impl/factory/PlatformModule.java | 34 ++---- .../DefaultFileSystemWatcherService.java | 97 +++++++++++++++ .../watcher/FileSystemWatcherService.java | 54 +++++++++ ...a => FileSystemWatcherServiceFactory.java} | 9 +- ... FileSystemWatcherServiceFactoryTest.java} | 17 ++- .../catchup/storecopy/LocalDatabase.java | 8 +- .../core/EnterpriseCoreEditionModule.java | 1 + .../EnterpriseReadReplicaEditionModule.java | 3 +- .../scenarios/CoreReplicationIT.java | 4 +- .../kernel/ha/cluster/SwitchToSlave.java | 2 + .../java/org/neo4j/ha/TestBranchedData.java | 2 +- 13 files changed, 393 insertions(+), 44 deletions(-) create mode 100644 community/io/src/main/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcher.java create mode 100644 community/io/src/test/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcherTest.java create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/DefaultFileSystemWatcherService.java create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherService.java rename community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/{WatcherLifecycleAdapterFactory.java => FileSystemWatcherServiceFactory.java} (83%) rename community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/{WatcherLifecycleAdapterFactoryTest.java => FileSystemWatcherServiceFactoryTest.java} (68%) diff --git a/community/io/src/main/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcher.java b/community/io/src/main/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcher.java new file mode 100644 index 0000000000000..006da16443a1c --- /dev/null +++ b/community/io/src/main/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcher.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.io.fs.watcher; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.neo4j.io.IOUtils; +import org.neo4j.io.fs.watcher.resource.WatchedResource; + +/** + * File system delegate that will remember all the files that it was asked to watch + * and will register them in real delegate during {@link #startWatching()} call. + * When delegate will be stopped all registered resources will be closed and delegate delegate will be stopped. + * + * Described pattern allows to perform repeatable startWatching/stopWatching cycle for pre-configured set of files. + */ +public class RestartableFileSystemWatcher implements FileWatcher +{ + private FileWatcher delegate; + private Set filesToWatch = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + private Set watchedResources = Collections.newSetFromMap( new ConcurrentHashMap<>() ); + + public RestartableFileSystemWatcher( FileWatcher delegate ) + { + this.delegate = delegate; + } + + @Override + public WatchedResource watch( File file ) throws IOException + { + filesToWatch.add( file ); + return WatchedResource.EMPTY; + } + + @Override + public void addFileWatchEventListener( FileWatchEventListener listener ) + { + delegate.addFileWatchEventListener( listener ); + } + + @Override + public void removeFileWatchEventListener( FileWatchEventListener listener ) + { + delegate.removeFileWatchEventListener( listener ); + } + + @Override + public void stopWatching() + { + try + { + IOUtils.closeAll( watchedResources ); + watchedResources.clear(); + } + catch ( IOException e ) + { + throw new UncheckedIOException( e ); + } + finally + { + delegate.stopWatching(); + } + } + + @Override + public void startWatching() throws InterruptedException + { + for ( File fileToWatch : filesToWatch ) + { + watchFile( fileToWatch ); + } + delegate.startWatching(); + } + + @Override + public void close() throws IOException + { + delegate.close(); + } + + private void watchFile( File fileToWatch ) + { + try + { + watchedResources.add( delegate.watch( fileToWatch ) ); + } + catch ( IOException e ) + { + throw new UncheckedIOException( e ); + } + } +} diff --git a/community/io/src/test/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcherTest.java b/community/io/src/test/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcherTest.java new file mode 100644 index 0000000000000..792a36210e488 --- /dev/null +++ b/community/io/src/test/java/org/neo4j/io/fs/watcher/RestartableFileSystemWatcherTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.io.fs.watcher; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +import org.neo4j.io.fs.watcher.resource.WatchedResource; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class RestartableFileSystemWatcherTest +{ + + private FileWatcher delegate = mock( FileWatcher.class ); + private RestartableFileSystemWatcher watcher = new RestartableFileSystemWatcher( delegate ); + + @Test + public void delegateListenersCallToRealWatcher() + { + FileWatchEventListener listener = mock( FileWatchEventListener.class ); + + watcher.addFileWatchEventListener( listener ); + verify( delegate ).addFileWatchEventListener( listener ); + + watcher.removeFileWatchEventListener( listener ); + verify( delegate ).removeFileWatchEventListener( listener ); + } + + @Test + public void closeDelegateOnClose() throws IOException + { + watcher.close(); + verify( delegate ).close(); + } + + @Test + public void startStopFileWatchingCycle() throws IOException, InterruptedException + { + File file1 = mock( File.class ); + File file2 = mock( File.class ); + WatchedResource resource1 = mock( WatchedResource.class ); + WatchedResource resource2 = mock( WatchedResource.class ); + watcher.watch( file1 ); + watcher.watch( file2 ); + + when( delegate.watch( file1 ) ).thenReturn( resource1 ); + when( delegate.watch( file2 ) ).thenReturn( resource2 ); + + int invocations = 100; + for ( int i = 0; i < invocations; i++ ) + { + startStopWatching(); + } + + verify( delegate, times( invocations ) ).watch( file1 ); + verify( delegate, times( invocations ) ).watch( file2 ); + verify( delegate, times( invocations ) ).startWatching(); + verify( delegate, times( invocations ) ).stopWatching(); + + verify( resource1, times( invocations ) ).close(); + verify( resource2, times( invocations ) ).close(); + } + + private void startStopWatching() throws InterruptedException + { + watcher.startWatching(); + watcher.stopWatching(); + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java index 5f0b7484bacdc..14bff6ddec987 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java @@ -21,20 +21,18 @@ import java.io.File; import java.io.IOException; -import java.util.List; import java.util.Map; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.security.URLAccessRule; -import org.neo4j.helpers.collection.Iterables; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemLifecycleAdapter; import org.neo4j.io.fs.watcher.FileWatcher; +import org.neo4j.io.fs.watcher.RestartableFileSystemWatcher; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.AvailabilityGuard; import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.extension.KernelExtensionFactory; import org.neo4j.kernel.extension.KernelExtensions; import org.neo4j.kernel.extension.UnsatisfiedDependencyStrategies; import org.neo4j.kernel.impl.api.LogRotationMonitor; @@ -51,7 +49,8 @@ import org.neo4j.kernel.impl.util.JobScheduler; import org.neo4j.kernel.impl.util.Neo4jJobScheduler; import org.neo4j.kernel.impl.util.watcher.DefaultFileDeletionEventListener; -import org.neo4j.kernel.impl.util.watcher.WatcherLifecycleAdapterFactory; +import org.neo4j.kernel.impl.util.watcher.FileSystemWatcherService; +import org.neo4j.kernel.impl.util.watcher.FileSystemWatcherServiceFactory; import org.neo4j.kernel.info.DiagnosticsManager; import org.neo4j.kernel.info.JvmChecker; import org.neo4j.kernel.info.JvmMetadataRepository; @@ -117,6 +116,8 @@ public class PlatformModule public final StoreCopyCheckPointMutex storeCopyCheckPointMutex; + public final FileSystemWatcherService watcherService; + public PlatformModule( File providedStoreDir, Map params, DatabaseInfo databaseInfo, GraphDatabaseFacadeFactory.Dependencies externalDependencies, GraphDatabaseFacade graphDatabaseFacade ) { @@ -176,8 +177,9 @@ public PlatformModule( File providedStoreDir, Config config, DatabaseInfo databa CheckPointerMonitor.class, tracers.checkPointTracer, CheckPointerMonitor.NULL ) ); FileWatcher fileWatcher = createFileWatcher(); - dependencies.satisfyDependencies( fileWatcher ); - life.add( WatcherLifecycleAdapterFactory.createLifecycleAdapter( jobScheduler, fileWatcher ) ); + watcherService = FileSystemWatcherServiceFactory.createFileSystemWatcherService( jobScheduler, fileWatcher ); + dependencies.satisfyDependencies( watcherService ); + life.add( watcherService ); pageCache = dependencies.satisfyDependency( createPageCache( fileSystem, config, logging, tracers ) ); life.add( new PageCacheLifecycle( pageCache ) ); @@ -212,7 +214,7 @@ protected FileWatcher createFileWatcher() { try { - FileWatcher watcher = fileSystem.fileWatcher(); + RestartableFileSystemWatcher watcher = new RestartableFileSystemWatcher( fileSystem.fileWatcher() ); watcher.addFileWatchEventListener( new DefaultFileDeletionEventListener( logging ) ); watcher.watch( storeDir ); // register to watch store dir parent folder to see when store dir removed @@ -324,22 +326,4 @@ protected TransactionStats createTransactionStats() return new TransactionStats(); } - private Iterable> getSettingsClasses( Iterable> settingsClasses, - Iterable> kernelExtensions ) - { - List> totalSettingsClasses = Iterables.asList( settingsClasses ); - - // Get the list of settings classes for extensions - for ( KernelExtensionFactory kernelExtension : kernelExtensions ) - { - Class settingsClass = kernelExtension.getSettingsClass(); - if ( settingsClass != null ) - { - totalSettingsClasses.add( settingsClass ); - } - } - - return totalSettingsClasses; - } - } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/DefaultFileSystemWatcherService.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/DefaultFileSystemWatcherService.java new file mode 100644 index 0000000000000..ffedd68dc2a7f --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/DefaultFileSystemWatcherService.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.impl.util.watcher; + +import java.util.concurrent.ThreadFactory; + +import org.neo4j.io.fs.watcher.FileWatcher; +import org.neo4j.kernel.impl.util.JobScheduler; + +/** + * Factory used for construction of proper adaptor for available {@link FileWatcher}. + * In case if silent matcher is used dummy adapter will be used, otherwise will use default wrapper that will bind + * monitoring cycles to corresponding lifecycle phases. + */ +public class DefaultFileSystemWatcherService implements FileSystemWatcherService +{ + private final JobScheduler jobScheduler; + private final FileWatcher fileWatcher; + private final FileSystemEventWatcher eventWatcher; + private ThreadFactory fileWatchers; + private Thread watcher; + + DefaultFileSystemWatcherService( JobScheduler jobScheduler, FileWatcher fileWatcher ) + { + this.jobScheduler = jobScheduler; + this.fileWatcher = fileWatcher; + this.eventWatcher = new FileSystemEventWatcher(); + } + + @Override + public void init() throws Throwable + { + fileWatchers = jobScheduler.threadFactory( JobScheduler.Groups.fileWatch ); + } + + @Override + public void start() throws Throwable + { + watcher = fileWatchers.newThread( eventWatcher ); + watcher.start(); + } + + @Override + public void stop() throws Throwable + { + eventWatcher.stopWatching(); + if ( watcher != null ) + { + watcher.interrupt(); + watcher.join(); + watcher = null; + } + } + + @Override + public void shutdown() throws Throwable + { + fileWatcher.close(); + } + + private class FileSystemEventWatcher implements Runnable + { + @Override + public void run() + { + try + { + fileWatcher.startWatching(); + } + catch ( InterruptedException ignored ) + { + } + } + + void stopWatching() + { + fileWatcher.stopWatching(); + } + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherService.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherService.java new file mode 100644 index 0000000000000..ea2d890c69378 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherService.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.impl.util.watcher; + +import org.neo4j.kernel.lifecycle.Lifecycle; + +/** + * Interface to be able to recognise file system watcher service in the set of discoverable services, + * need to extend {@link Lifecycle} since service should be restartable in clustering setup + * (for example during store branching) + */ +public interface FileSystemWatcherService extends Lifecycle +{ + FileSystemWatcherService EMPTY_WATCHER = new FileSystemWatcherService() + { + @Override + public void init() throws Throwable + { + } + + @Override + public void start() throws Throwable + { + } + + @Override + public void stop() throws Throwable + { + } + + @Override + public void shutdown() throws Throwable + { + } + }; + +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactory.java similarity index 83% rename from community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactory.java rename to community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactory.java index 5b041016c2954..a5814b285109e 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactory.java @@ -21,20 +21,19 @@ import org.neo4j.io.fs.watcher.FileWatcher; import org.neo4j.kernel.impl.util.JobScheduler; -import org.neo4j.kernel.lifecycle.LifecycleAdapter; /** * Factory used for construction of proper adaptor for available {@link FileWatcher}. * In case if silent matcher is used dummy adapter will be used, otherwise will use default wrapper that will bind * monitoring cycles to corresponding lifecycle phases. */ -public class WatcherLifecycleAdapterFactory +public class FileSystemWatcherServiceFactory { - public static LifecycleAdapter createLifecycleAdapter( JobScheduler jobScheduler, FileWatcher fileWatcher ) + public static FileSystemWatcherService createFileSystemWatcherService( JobScheduler jobScheduler, FileWatcher fileWatcher ) { - return FileWatcher.SILENT_WATCHER.equals( fileWatcher ) ? new LifecycleAdapter() - : new FileWatcherLifecycleAdapter( jobScheduler, + return FileWatcher.SILENT_WATCHER.equals( fileWatcher ) ? FileSystemWatcherService.EMPTY_WATCHER + : new DefaultFileSystemWatcherService( jobScheduler, fileWatcher ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactoryTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactoryTest.java similarity index 68% rename from community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactoryTest.java rename to community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactoryTest.java index b7d0984bd14b2..b9e1a42b62f4b 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/WatcherLifecycleAdapterFactoryTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/watcher/FileSystemWatcherServiceFactoryTest.java @@ -24,13 +24,12 @@ import org.neo4j.io.fs.watcher.FileWatcher; import org.neo4j.kernel.impl.util.JobScheduler; -import org.neo4j.kernel.lifecycle.LifecycleAdapter; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; -public class WatcherLifecycleAdapterFactoryTest +public class FileSystemWatcherServiceFactoryTest { private JobScheduler scheduler = mock( JobScheduler.class ); @@ -38,16 +37,16 @@ public class WatcherLifecycleAdapterFactoryTest @Test public void createDummyAdapterForSilentWatcher() { - LifecycleAdapter adapter = - WatcherLifecycleAdapterFactory.createLifecycleAdapter( scheduler, FileWatcher.SILENT_WATCHER ); - assertEquals( adapter.getClass(), LifecycleAdapter.class ); + FileSystemWatcherService service = + FileSystemWatcherServiceFactory.createFileSystemWatcherService( scheduler, FileWatcher.SILENT_WATCHER ); + assertSame( service, FileSystemWatcherService.EMPTY_WATCHER ); } @Test public void createDefaultWatcherAdapter() { - LifecycleAdapter adapter = - WatcherLifecycleAdapterFactory.createLifecycleAdapter( scheduler, mock( FileWatcher.class ) ); - assertThat( adapter, Matchers.instanceOf( FileWatcherLifecycleAdapter.class ) ); + FileSystemWatcherService service = + FileSystemWatcherServiceFactory.createFileSystemWatcherService( scheduler, mock( FileWatcher.class ) ); + assertThat( service, Matchers.instanceOf( DefaultFileSystemWatcherService.class ) ); } } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/catchup/storecopy/LocalDatabase.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/catchup/storecopy/LocalDatabase.java index 0d8856a4a69da..d3f78312446c1 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/catchup/storecopy/LocalDatabase.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/catchup/storecopy/LocalDatabase.java @@ -37,6 +37,7 @@ import org.neo4j.kernel.impl.storemigration.StoreFile; import org.neo4j.kernel.impl.transaction.log.TransactionAppender; import org.neo4j.kernel.impl.transaction.state.DataSourceManager; +import org.neo4j.kernel.impl.util.watcher.FileSystemWatcherService; import org.neo4j.kernel.internal.DatabaseHealth; import org.neo4j.kernel.lifecycle.Lifecycle; import org.neo4j.logging.Log; @@ -59,6 +60,7 @@ public class LocalDatabase implements Lifecycle private final Supplier databaseHealthSupplier; private final AvailabilityGuard availabilityGuard; private final Log log; + private final FileSystemWatcherService watcherService; private volatile StoreId storeId; private volatile DatabaseHealth databaseHealth; @@ -67,7 +69,8 @@ public class LocalDatabase implements Lifecycle private volatile TransactionCommitProcess localCommit; public LocalDatabase( File storeDir, StoreFiles storeFiles, DataSourceManager dataSourceManager, - Supplier databaseHealthSupplier, AvailabilityGuard availabilityGuard, + Supplier databaseHealthSupplier, FileSystemWatcherService watcherService, + AvailabilityGuard availabilityGuard, LogProvider logProvider ) { this.storeDir = storeDir; @@ -75,6 +78,7 @@ public LocalDatabase( File storeDir, StoreFiles storeFiles, DataSourceManager da this.dataSourceManager = dataSourceManager; this.databaseHealthSupplier = databaseHealthSupplier; this.availabilityGuard = availabilityGuard; + this.watcherService = watcherService; this.log = logProvider.getLog( getClass() ); raiseAvailabilityGuard( NOT_STOPPED ); @@ -93,6 +97,7 @@ public synchronized void start() throws Throwable log.info( "Starting with storeId: " + storeId ); dataSourceManager.start(); + watcherService.start(); dropAvailabilityGuard(); } @@ -220,6 +225,7 @@ private synchronized void stopWithRequirement( AvailabilityRequirement requireme raiseAvailabilityGuard( requirement ); databaseHealth = null; localCommit = null; + watcherService.stop(); dataSourceManager.stop(); } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java index 3123615106ce8..3e2d3f10dc549 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java @@ -165,6 +165,7 @@ public void registerEditionSpecificProcedures( Procedures procedures ) throws Ke new StoreFiles( fileSystem, platformModule.pageCache ), platformModule.dataSourceManager, databaseHealthSupplier, + platformModule.watcherService, platformModule.availabilityGuard, logProvider ); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java index 8e4cd5a989e61..81edfaf339b09 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java @@ -206,7 +206,8 @@ public void registerEditionSpecificProcedures( Procedures procedures ) throws Ke StoreFiles storeFiles = new StoreFiles( fileSystem, pageCache ); LocalDatabase localDatabase = new LocalDatabase( platformModule.storeDir, storeFiles, platformModule.dataSourceManager, - databaseHealthSupplier, platformModule.availabilityGuard, logProvider ); + databaseHealthSupplier, platformModule.watcherService, platformModule.availabilityGuard, + logProvider ); RemoteStore remoteStore = new RemoteStore( platformModule.logging.getInternalLogProvider(), fileSystem, platformModule.pageCache, diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/CoreReplicationIT.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/CoreReplicationIT.java index 4290ad0dd1156..48ad88b888f4d 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/CoreReplicationIT.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/CoreReplicationIT.java @@ -51,8 +51,8 @@ public class CoreReplicationIT { @Rule - public final ClusterRule clusterRule = - new ClusterRule( getClass() ).withNumberOfCoreMembers( 3 ).withNumberOfReadReplicas( 0 ); + public final ClusterRule clusterRule = new ClusterRule( getClass() ) + .withNumberOfCoreMembers( 3 ).withNumberOfReadReplicas( 0 ); @Rule public SuppressOutput suppressOutput = SuppressOutput.suppressAll(); diff --git a/enterprise/ha/src/main/java/org/neo4j/kernel/ha/cluster/SwitchToSlave.java b/enterprise/ha/src/main/java/org/neo4j/kernel/ha/cluster/SwitchToSlave.java index 0e58a0993f5b5..80b1792240760 100644 --- a/enterprise/ha/src/main/java/org/neo4j/kernel/ha/cluster/SwitchToSlave.java +++ b/enterprise/ha/src/main/java/org/neo4j/kernel/ha/cluster/SwitchToSlave.java @@ -74,6 +74,7 @@ import org.neo4j.kernel.impl.transaction.log.MissingLogDataException; import org.neo4j.kernel.impl.transaction.log.TransactionIdStore; import org.neo4j.kernel.impl.transaction.state.DataSourceManager; +import org.neo4j.kernel.impl.util.watcher.FileSystemWatcherService; import org.neo4j.kernel.internal.StoreLockerLifecycleAdapter; import org.neo4j.kernel.lifecycle.LifeSupport; import org.neo4j.kernel.lifecycle.Lifecycle; @@ -101,6 +102,7 @@ public abstract class SwitchToSlave TransactionCommittingResponseUnpacker.class, IndexConfigStore.class, OnlineBackupKernelExtension.class, + FileSystemWatcherService.class }; private final StoreCopyClient storeCopyClient; private final Function slaveServerFactory; diff --git a/enterprise/ha/src/test/java/org/neo4j/ha/TestBranchedData.java b/enterprise/ha/src/test/java/org/neo4j/ha/TestBranchedData.java index f2122dcc9a584..178c5b0525aae 100644 --- a/enterprise/ha/src/test/java/org/neo4j/ha/TestBranchedData.java +++ b/enterprise/ha/src/test/java/org/neo4j/ha/TestBranchedData.java @@ -32,6 +32,7 @@ import java.util.function.Consumer; import org.neo4j.cluster.ClusterSettings; +import org.neo4j.com.storecopy.StoreUtil; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.ResourceIterator; @@ -50,7 +51,6 @@ import org.neo4j.kernel.impl.ha.ClusterManager.RepairKit; import org.neo4j.kernel.impl.logging.StoreLogService; import org.neo4j.kernel.impl.util.Listener; -import org.neo4j.com.storecopy.StoreUtil; import org.neo4j.kernel.lifecycle.LifeRule; import org.neo4j.kernel.monitoring.Monitors; import org.neo4j.storageengine.api.StoreFileMetadata;