-
Notifications
You must be signed in to change notification settings - Fork 582
Enhancement implemented #2954 : Recover from fatal invalid cache state #3103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
1464115
7f28e7c
a6a61b1
a6b7039
5012e92
a6265de
ecf166c
0f5098a
ceebfe4
ea0eb35
2fbc98c
76287e7
93969c4
976a137
79d042e
cc87d58
c6cfcab
15821b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,6 +60,10 @@ private boolean isStarted() { | |
| @Override | ||
| public void start(final ServiceProvider<Service> serviceProvider) { | ||
| innerStart(serviceProvider); | ||
| if (persistenceService != null && !persistenceService.isClean()) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't need to null-check here. Persistence service should always be non-null because we depend on it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @chrisdennis
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to look at the |
||
| destroyAll(); | ||
| LOGGER.info("Probably unclean shutdown was done, so deleted root directory."); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -73,10 +77,6 @@ public void startForMaintenance(ServiceProvider<? super MaintainableService> ser | |
| private void innerStart(ServiceProvider<? super MaintainableService> serviceProvider) { | ||
| persistenceService = serviceProvider.getService(LocalPersistenceService.class); | ||
| isStarted = true; | ||
| if (persistenceService!=null && persistenceService.isServiceStarted() && !persistenceService.isClean()) { | ||
| destroyAll(); | ||
| LOGGER.info("Probably unclean shutdown was done, so deleted root directory."); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,12 +144,14 @@ public synchronized void stop() { | |
| if (cleanFile.createNewFile()) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably log some kind of warning on a false return here too. |
||
| LOGGER.debug("clean file is created."); | ||
| } else { | ||
| LOGGER.warn("clean file already exists. It's not deleted either user's permission or network issue." + | ||
| "\n Hint: clean file exists on service startup, indicates service was stopped cleanly last time. It gets created while the service is stopped and it should be deleted while the service is started."); | ||
| LOGGER.warn("clean file already exists. The file didn't got deleted, may be due to network issue or file permission on directory." + | ||
| "\n Hint: clean file exists on service start-up, indicates service was stopped cleanly last time. It gets created while the service is stopped and it should be deleted while the service is started." + | ||
| "\n Action: Please verify there permission to delete the file and delete the root directory prior to start the service again."); | ||
| } | ||
| } catch (IOException e) { | ||
| LOGGER.warn("clean file is not created. Reason: " + e.getMessage() + | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This log line suffers the same problem. It's long, wordy, but doesn't help the user. |
||
| "\n Hint: clean file exists on service startup, indicates service was stopped cleanly last time. It gets created while the service is stopped and it should be deleted while the service is started."); | ||
| "\n Hint: clean file exists on service start-up, indicates service was stopped cleanly last time. It gets created while the service is stopped and it should be deleted while the service is started." + | ||
| "\n Action: Do resolve the exception received. Prior to start the service again, please delete the root directory."); | ||
| } | ||
| try { | ||
| lock.release(); | ||
|
|
@@ -237,10 +239,6 @@ public void destroyAll(String owner) { | |
|
|
||
| /** | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This javadoc isn't needed once we fix up the interface method javadoc. |
||
| * {@inheritDoc} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to keep an |
||
| * Abnormally stopped service may lead to data corruption. | ||
| * Can take appropriate action by identifying state of service stopped. | ||
| * | ||
| * @throws IllegalStateException if service is not running. | ||
| */ | ||
| @Override | ||
| public final synchronized boolean isClean() { | ||
|
|
@@ -251,14 +249,6 @@ public final synchronized boolean isClean() { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public final boolean isServiceStarted() { | ||
| return started; | ||
| } | ||
|
|
||
| private void destroy(SafeSpace ss, boolean verbose) { | ||
| if (verbose) { | ||
| LOGGER.debug("Destroying file based persistence context for {}", ss.identifier); | ||
|
|
@@ -270,7 +260,6 @@ private void destroy(SafeSpace ss, boolean verbose) { | |
| } | ||
| } | ||
|
|
||
|
|
||
| private SafeSpace createSafeSpaceLogical(String owner, String identifier) { | ||
| File ownerDirectory = new File(rootDirectory, owner); | ||
| File directory = new File(ownerDirectory, safeIdentifier(identifier)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,32 +144,44 @@ public void testExclusiveLock() throws IOException { | |
| } | ||
|
|
||
| @Test | ||
| public void testServiceStoppedStatusWhenStoppedCleanly() throws IOException { | ||
| File f = folder.newFolder("testServiceStoppedStatusWhenStoppedCleanly"); | ||
| public void testServiceShutdownWithEmptyDirectory() throws IOException { | ||
| File f = folder.newFolder("testServiceShutdownWithEmptyDirectory"); | ||
| final DefaultLocalPersistenceService service = new DefaultLocalPersistenceService(new DefaultPersistenceConfiguration(f)); | ||
| service.start(null); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test should actually create a file inside the directory to ensure we hit the non-empty directory codepath. |
||
| assertTrue(service.isClean()); | ||
| service.stop(); | ||
| service.start(null); | ||
| assertTrue(service.isClean()); | ||
| service.stop(); | ||
| } | ||
|
|
||
| @Test | ||
| public void testServiceStoppedStatusWhenStoppedUnexpectedly() throws IOException { | ||
| // Service stopped unexpectedly means directory exists with some data but without .clean file. | ||
| File f = folder.newFolder("testServiceStoppedStatusWhenStoppedUnexpectedly"); | ||
| public void testServiceShutdownWithNonEmptyDirectory() throws IOException { | ||
| File f = folder.newFolder("testServiceShutdownWithNonEmptyDirectory"); | ||
| final DefaultLocalPersistenceService service = new DefaultLocalPersistenceService(new DefaultPersistenceConfiguration(f)); | ||
| new File(f, "dummy.txt").createNewFile(); | ||
| new File(f, ".clean").createNewFile(); | ||
| service.start(null); | ||
| assertTrue(service.isClean()); | ||
| service.stop(); | ||
| } | ||
|
|
||
| @Test | ||
| public void testServiceShutdownUnexpectedly() throws IOException { | ||
| // Service shutdown unexpectedly means directory exists with some data but without .clean file. | ||
| File f = folder.newFolder("testServiceShutdownUnexpectedly"); | ||
| final DefaultLocalPersistenceService service = new DefaultLocalPersistenceService(new DefaultPersistenceConfiguration(f)); | ||
| new File(f.getAbsolutePath()+"\\dummy.txt").createNewFile(); | ||
| new File(f, "dummy.txt").createNewFile(); | ||
| service.start(null); | ||
| assertFalse(service.isClean()); | ||
| service.stop(); | ||
| } | ||
|
|
||
| @Test | ||
| public void testServiceStoppedStatusIfServiceIsNotRunning() throws IOException { | ||
| public void testServiceShutdownStatusIfServiceIsNotRunning() throws IOException { | ||
| File f = folder.newFolder("testServiceShutdownStatusIfServiceIsNotRunning"); | ||
| final DefaultLocalPersistenceService service = new DefaultLocalPersistenceService(new DefaultPersistenceConfiguration(f)); | ||
| try { | ||
| File f = folder.newFolder("testServiceStoppedStatusIfServiceIsNotRunning"); | ||
| final DefaultLocalPersistenceService service = new DefaultLocalPersistenceService(new DefaultPersistenceConfiguration(f)); | ||
| service.isClean(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only the method call being tested should be inside the try-catch block. |
||
| fail("Expected IllegalStateException"); | ||
| } catch(IllegalStateException e) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Javadoc needs polish, and the
@throwsshould be moved up to here: