I seem to be cursed with hitting obscure issues (or am just getting worse at debugging).
Here goes -
As a follow-on from my adventures with partial comparators (see:
2412766 I've moved to working with a secondary database to maintain a secondary ordering (ie: uniqueness being handled with one key, ordering being handled by a secondary).
Everything seems to work perfectly on
puts(), however, as soon as I attempt a
delete(), I get:
----
Exception in thread "main" com.sleepycat.je.SecondaryIntegrityException: (JE 5.0.55) Secondary is corrupt: the primary record contains a key that is not present in the secondary
at com.sleepycat.je.SecondaryDatabase.deleteKey(SecondaryDatabase.java:938)
at com.sleepycat.je.SecondaryDatabase.updateSecondary(SecondaryDatabase.java:853)
at com.sleepycat.je.SecondaryTrigger.databaseUpdated(SecondaryTrigger.java:41)
at com.sleepycat.je.Database.notifyTriggers(Database.java:2144)
at com.sleepycat.je.Database.deleteInternal(Database.java:930)
at com.sleepycat.je.Database.delete(Database.java:828)
at com.xxx.yyy.db.BDBCalendarStorageBackend.indexCalendar(BDBCalendarStorageBackend.java:113)
at com.xxx.yyy.indexer.TicketIndexer.indexDeltaLogs(TicketIndexer.java:239)
at com.xxx.yyy.cli.DeltaLogTool.run(DeltaLogTool.java:63)
at com.xxx.yyy.cli.AbstractBaseCommand.execute(AbstractBaseCommand.java:114)
at com.xxx.yyy.cli.DeltaLogTool.main(DeltaLogTool.java:85)
----
I've done a fair amount of reading, and believe I'm doing things correctly (though obviously, not quite :) - Specifically:
- Both DBs are transactional
- The secondary key creator has no external state/is totally deterministic
- I've started from a clean DB (so creator/comparators aren't deserialized)
- I'm only writing to the primary DB (not touching secondary directly at all)
Basic DB opening code is this:
----
// Setup primary DB config
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setAllowCreate(true);
dbConfig.setSortedDuplicates(false);
dbConfig.setTransactional(true);
dbConfig.setBtreeComparator(new IndexKeyBinding.PrimaryKeyComparator());
// Setup secondary DB config
SecondaryConfig db2Config = new SecondaryConfig();
db2Config.setAllowCreate(true);
db2Config.setTransactional(true);
db2Config.setSortedDuplicates(true); // Required for secondary (<route><cost> is not unique)
db2Config.setBtreeComparator(new IndexKeyBinding.SecondaryKeyComparator());
db2Config.setKeyCreator(new IndexKeyBinding.RouteCostKeyCreator());
----
Key creator code is viewable here: https://gist.github.com/8b49086b57bc80ab4a15
I've fiddled my key format quite a bit, because I was having some interesting issues with the
primaryKeyEntry returning more bytes than are actually in the key. Despite my efforts, nothing seems to have made any difference.
My secondary key is entirely created as a composite of my primaryKey and primaryValue (data) and I've put in a bunch of debugging statements in the key creator to ensure that the data being encoded is as I expect and it's all looking OK, so I'm a bit stuck as to what to look at next.
Update: I've tried removing the custom secondary btree comparator (as I'm not practically using it) and it sadly makes no difference.
Edited by: fb on Jul 11, 2012 1:58 AM
Edited by: fb on Jul 16, 2012 7:32 PM