Skip to content

Commit c96f3d7

Browse files
authored
Merge pull request #350 from alanprot/AMQ-7163
AMQ-7163 - If the broker had an unclean shutdown and number of free p…
2 parents c46965c + cd1d5eb commit c96f3d7

File tree

2 files changed

+57
-0
lines changed
  • activemq-kahadb-store/src

2 files changed

+57
-0
lines changed

activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/disk/page/PageFile.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ private void recoverFreePages(final long lastRecoveryPage) throws Exception {
485485

486486
// allow flush (with index lock held) to merge eventually
487487
recoveredFreeList.lazySet(newFreePages);
488+
} else {
489+
// If there is no free pages, set trackingFreeDuringRecovery to allow the broker to have a clean shutdown
490+
trackingFreeDuringRecovery.set(null);
488491
}
489492
}
490493

@@ -558,6 +561,10 @@ public boolean isLoaded() {
558561
return loaded.get();
559562
}
560563

564+
public boolean isCleanShutdown() {
565+
return metaData != null && metaData.isCleanShutdown();
566+
}
567+
561568
public void allowIOResumption() {
562569
loaded.set(true);
563570
}

activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/disk/page/PageFileTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,56 @@ public boolean isSatisified() throws Exception {
361361
}, 12000000));
362362
}
363363

364+
public void testRecoveryAfterUncleanShutdownAndZeroFreePages() throws Exception {
365+
final int numberOfPages = 1000;
366+
final AtomicBoolean recoveryEnd = new AtomicBoolean();
367+
368+
Appender appender = new DefaultTestAppender() {
369+
@Override
370+
public void doAppend(LoggingEvent event) {
371+
if (event.getLevel().equals(Level.INFO) && event.getMessage().toString().contains("Recovered pageFile free list")) {
372+
recoveryEnd.set(true);
373+
}
374+
}
375+
};
376+
377+
org.apache.log4j.Logger log4jLogger =
378+
org.apache.log4j.Logger.getLogger(PageFile.class);
379+
log4jLogger.addAppender(appender);
380+
log4jLogger.setLevel(Level.DEBUG);
381+
382+
PageFile pf = new PageFile(new File("target/test-data"), getName());
383+
pf.delete();
384+
pf.setEnableRecoveryFile(false);
385+
pf.load();
386+
387+
LOG.info("Creating Transactions");
388+
for (int i = 0; i < numberOfPages; i++) {
389+
Transaction tx = pf.tx();
390+
Page page = tx.allocate();
391+
String t = "page:" + i;
392+
page.set(t);
393+
tx.store(page, StringMarshaller.INSTANCE, false);
394+
tx.commit();
395+
}
396+
397+
pf.flush();
398+
399+
assertEquals(pf.getFreePageCount(), 0);
400+
401+
//Simulate an unclean shutdown
402+
PageFile pf2 = new PageFile(new File("target/test-data"), getName());
403+
pf2.setEnableRecoveryFile(false);
404+
pf2.load();
405+
406+
assertTrue("Recovery Finished", Wait.waitFor(recoveryEnd::get, 100000));
407+
408+
//Simulate a clean shutdown
409+
pf2.unload();
410+
assertTrue(pf2.isCleanShutdown());
411+
412+
}
413+
364414
public void testBackgroundWillMarkUsedPagesAsFreeInTheBeginning() throws Exception {
365415
final int numberOfPages = 100000;
366416
final AtomicBoolean recoveryEnd = new AtomicBoolean();

0 commit comments

Comments
 (0)