Library Version 11.2.5.0, Release 5.0.104
The change is forward compatible in that JE files created with release 4.1 and earlier can be read when opened with JE 5.0.104. The change is not backward compatible in that files created with JE 5.0 cannot be read by earlier releases. Note that if an existing environment is opened read/write, a new log file is written by JE 5.0 and the environment can no longer be read by earlier releases.
There are two important notes about the file format change.
One of two utility programs must be used, which are available in the release package for JE 4.1.20, or a later release of JE 4.1. If you are currently running a release earlier than JE 4.1.20, then you must download the latest JE 4.1 release package in order to run these utilities.
The steps for upgrading are as follows.
Environment
:
java -jar je-4.1.20.jar DbPreUpgrade_4_1 -h <dir>If you are using a JE
ReplicatedEnvironment
:
java -jar je-4.1.20.jar DbRepPreUpgrade_4_1 -h <dir> -groupName <group name> -nodeName <node name> -nodeHostPort <host:port>
The second step -- running the utility program -- does not perform data conversion. This step simply performs a special checkpoint to prepare the environment for upgrade. It should take no longer than an ordinary startup and shutdown.
During the last step -- when the application opens the JE environment using the
current release (JE 5 or later) -- all databases configured for duplicates will
automatically be converted before the Environment
or
ReplicatedEnvironment
constructor returns. Note that a database
might be explicitly configured for duplicates using
DatabaseConfig.setSortedDuplicates(true)
, or implicitly configured
for duplicates by using a DPL MANY_TO_XXX relationship
(Relationship.MANY_TO_ONE
or
Relationship.MANY_TO_MANY
).
The duplicate database conversion only rewrites internal nodes in the Btree, not leaf nodes. In a test with a 500 MB cache, conversion of a 10 million record data set (8 byte key and data) took between 1.5 and 6.5 minutes, depending on number of duplicates per key. The high end of this range is when 10 duplicates per key were used; the low end is with 1 million duplicates per key.
To make the duplicate database conversion predictable during deployment, users
should measure the conversion time on a non-production system before upgrading
a deployed system. When duplicates are converted, the Btree internal nodes are
preloaded into the JE cache. A new configuration option,
EnvironmentConfig.ENV_DUP_CONVERT_PRELOAD_ALL
, can be set to false
to optimize this process if the cache is not large enough to hold the internal
nodes for all databases. For more information, see the javadoc for this
property.
If an application has no databases configured for duplicates, then the last step simply opens the JE environment normally, and no data conversion is performed.
If the user fails to run the DbPreUpgrade_4_1 or DbRepPreUpgrade_4_1 utility
program before opening an environment with JE 5 for the first time, an
exception such as the following will normally be thrown by the
Environment
or ReplicatedEnvironment
constructor:
com.sleepycat.je.EnvironmentFailureException: (JE 5.0.46) JE 4.1 duplicate DB entries were found in the recovery interval. Before upgrading to JE 5.0, the following utility must be run using JE 4.1 (4.1.20 or later): DbPreUpgrade_4_1. See the change log. UNEXPECTED_STATE: Unexpected internal state, may have side effects. at com.sleepycat.je.EnvironmentFailureException.unexpectedState(EnvironmentFailureException.java:376) at com.sleepycat.je.recovery.RecoveryManager.checkLogVersion8UpgradeViolations(RecoveryManager.java:2694) at com.sleepycat.je.recovery.RecoveryManager.buildTree(RecoveryManager.java:549) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:198) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:610) ...
If the user fails to run the DbPreUpgrade_4_1 or DbRepPreUpgrade_4_1 utility
program, but no exception is thrown when the environment is opened with JE 5,
this is probably because the application performed an
Environment.sync
before last closing the environment with JE 4.1
or earlier, and nothing else happened to be written (by the application or JE
background threads) after the sync operation. In this case, running the
upgrade utility is not necessary.
[#23132] (5.0.104)
Caused by: java.lang.IllegalStateException: Can't overwrite cause at java.lang.Throwable.initCause(Throwable.java:320) at com.sleepycat.je.dbi.EnvironmentImpl.invalidate(EnvironmentImpl.java:1529) ...[#22837] (5.0.98)
com.sleepycat.je.EnvironmentFailureException: (JE 5.0.86) Latch not held: IN1419 UNEXPECTED_STATE: Unexpected internal state, may have side effects. at com.sleepycat.je.EnvironmentFailureException.unexpectedState(EnvironmentFailureException.java:390) at com.sleepycat.je.latch.SharedLatch.release(SharedLatch.java:181) at com.sleepycat.je.tree.IN.releaseLatch(IN.java:551) at com.sleepycat.je.tree.Tree.getNextIN(Tree.java:1120) at com.sleepycat.je.tree.Tree.getNextBin(Tree.java:935) at com.sleepycat.je.dbi.CursorImpl.getNext(CursorImpl.java:1666) ...[#22772] (5.0.97)
Caused by: com.sleepycat.je.SecondaryIntegrityException: (JE 5.0.83) Secondary refers to a missing key in the primary database at com.sleepycat.je.Database.secondaryRefersToMissingPrimaryKey(Database.java:2252) at com.sleepycat.je.Cursor.readPrimaryAfterGet(Cursor.java:3882) at com.sleepycat.je.SecondaryCursor.readPrimaryAfterGet(SecondaryCursor.java:1519) at com.sleepycat.je.SecondaryCursor.retrieveNext(SecondaryCursor.java:1495) at com.sleepycat.je.SecondaryCursor.getNext(SecondaryCursor.java:601) ...[#22603] (5.0.97)
2013-08-29 19:41:45.965 UTC SEVERE [.] -XX:+UseCompressedOops was specified but is not in effect, probably because the heap size is too large for this JVM option on this platform. This is likely to cause an OutOfMemoryError!Note that in this situation, and presumably on all JVMs, the JVM itself also outputs a warning message at startup such as the following:
OpenJDK 64-Bit Server VM warning: Max heap size too large for Compressed Oops[#22657] (5.0.97)
Caused by: java.lang.IllegalArgumentException: toKey out of range at java.util.TreeMap$AscendingSubMap.headMap(TreeMap.java:1719) at java.util.TreeSet.headSet(TreeSet.java:338) at java.util.TreeSet.headSet(TreeSet.java:372) at com.sleepycat.je.cleaner.Cleaner.deleteSafeToDeleteFiles(Cleaner.java:739) at com.sleepycat.je.cleaner.Cleaner.updateFilesAtCheckpointEnd(Cleaner.java:935) at com.sleepycat.je.recovery.Checkpointer.doCheckpoint(Checkpointer.java:797) at com.sleepycat.je.recovery.Checkpointer.onWakeup(Checkpointer.java:508) at com.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:148)This problem could occur in rare circumstances when using the DbBackUp or DiskOrderedCursor APIs. [#22822] (5.0.97)
java.net.InetAddress.getLocalHost() returned loopback address: <hostname> and no suitable address associated with network interfaces.This could only realistically happen when developing, testing, or demo-ing a JE HA application, but was still an inconvenience. [#22252] (5.0.74)
Application-supplied statistics may also be added to the JE statistics file so they may be easily correlated with JE statistics.
See the following new APIs related to the above new features:
Added a feature that enables the ability to log information about the Environment configuration. The Environment configuration log file may be updated at Environment creation/open time or if the Environment configuration is altered. The name of the file is je.config.csv. The file resides in the same directory as the je.stats.csv file. This file will contain a maximum of 1000 rows before it is rolled over. Only one version of the file is retained. The name of the previous version is je.config.1.csv.
Fixed a problem that corrects the value for the avgBatch statistic. The number of batches was being cleared unconditionally when the statistic was acquired. It is now cleared only if StatConfig.setClear() is true.
Fixed a problem that corrects the value of the nRootSplits statistic. The value of the statistic was never cleared. It is now cleared if StatConfig.setClear() is true.
Added the com.sleepycat.je.util.DbFilterStats utility. The utility allows the ability to specify columns of the statistics file to project. [#22009] (5.0.76)
NetworkRestore.execute
method, causing it to skip that
log provider and try the next one. This change prevents the network
restore operation from spreading log file corruption to other
nodes.
As part of this change, also added the
LogVerificationReadableByteChannel
utility class for
verifying log file checksums when copying log files using NIO channels,
to provide better copying performance.
[#21029] (5.0.76)
[#22394] (5.0.76)
Caused by: com.sleepycat.je.EnvironmentFailureException: ... last LSN=0x21f/0x26 LOG_INTEGRITY: Log information is incorrect, problem is likely persistent. Environment is invalid and must be closed. at com.sleepycat.je.recovery.RecoveryManager.traceAndThrowException(RecoveryManager.java:3090) at com.sleepycat.je.recovery.RecoveryManager.undoLNs(RecoveryManager.java:1141) at com.sleepycat.je.recovery.RecoveryManager.buildTree(RecoveryManager.java:479) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:174) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:549) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:237) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:229) at com.sleepycat.je.Environment.This problem is very unlikely to occur -- the bug has always been present in JE but was recently reported for the first time. It may be more likely to occur for applications that have long transactions. If the problem does occur using an earlier version of JE, upgrading to JE 4.1.29 or later will allow the Environment to be opened and no data loss will occur. [#22407] (5.0.76)(Environment.java:211) at com.sleepycat.je.Environment. (Environment.java:165) ... Caused by: com.sleepycat.je.EnvironmentFailureException: ... Cannot read backward over cleaned file from 543 to 539 LOG_INTEGRITY: Log information is incorrect, problem is likely persistent. Environment is invalid and must be closed. at com.sleepycat.je.log.FileReader.setBackwardPosition(FileReader.java:537) at com.sleepycat.je.log.FileReader.getLogEntryInReadBuffer(FileReader.java:429) at com.sleepycat.je.log.FileReader.readNextEntryAllowExceptions(FileReader.java:256) at com.sleepycat.je.log.FileReader.readNextEntry(FileReader.java:229) at com.sleepycat.je.recovery.RecoveryManager.undoLNs(RecoveryManager.java:1053) ...
SyncPolicy.SYNC
, when the transactions are replayed at the
replica. These changes can provide significant throughput increase and latency
reductions for high throughput applications that
require SyncPolicy.SYNC
durability.
This group commit behavior can be controlled by two new replication
configuration parameters:
com.sleepycat.je.rep.ReplicationConfig.REPLICA_MAX_GROUP_COMMIT
and
com.sleepycat.je.rep.ReplicationConfig.REPLICA_GROUP_COMMIT_INTERVAL
.
The following new methods defined on the
class com.sleepycat.je.rep.ReplicatedEnvironmentStats
provide
information that can help tune the replica group commit configuration parameters:
getNReplayGroupCommitTimeouts()
getNReplayGroupCommitMaxExceeded()
getNReplayGroupCommitTxns()
getNReplayGroupCommits()
Please consult the javadoc for these methods and configuration parameters for additional details. [#22347] (5.0.77)
Exception in thread "pool-1-thread-1" java.lang.NullPointerException at com.sleepycat.je.rep.utilint.BinaryProtocol$SimpleMessage.getMessageSize(BinaryProtocol.java:757) at com.sleepycat.je.rep.utilint.BinaryProtocol$SimpleMessage.wireFormat(BinaryProtocol.java:662) at com.sleepycat.je.rep.utilint.BinaryProtocol$RejectMessage.wireFormat(BinaryProtocol.java:864) at com.sleepycat.je.rep.utilint.BinaryProtocol.write(BinaryProtocol.java:544) at com.sleepycat.je.rep.utilint.BinaryProtocol.write(BinaryProtocol.java:532) at com.sleepycat.je.rep.impl.BinaryNodeStateService$NodeStateServiceRunnable.run(BinaryNodeStateService.java:127 ...The problem was due to faulty exception handling, and theoretically could manifest at any time during the life of a JE replication node, although it seems most likely to happen in reaction to network induced IOExceptions. The replication node would be invalidated, and would need to be re-opened by the application. The problem is transient, and does not affect the data stored persistently.
Thanks to Keith Wall for reporting this on OTN. [#22525] (5.0.77)
This group commit behavior can be controlled by two new environment
configuration parameters:
com.sleepycat.je.EnvironmentConfig.LOG_GROUP_COMMIT_INTERVAL
and
com.sleepycat.je.EnvironmentConfig.LOG_GROUP_COMMIT_THRESHOLD
.
Please consult the javadoc for for additonal detail regarding these configuration parameters. [#22535] (5.0.78)
java.lang.IndexOutOfBoundsException: -2363 is negative. at com.sleepycat.je.utilint.BitMap.set(BitMap.java:50) at com.sleepycat.je.util.DbScavenger.checkProcessEntry(DbScavenger.java:249) at com.sleepycat.je.util.DbScavenger.processDbTreeEntry(DbScavenger.java:296) at com.sleepycat.je.util.DbScavenger.access$000(DbScavenger.java:60) at com.sleepycat.je.util.DbScavenger$1.processEntryCallback(DbScavenger.java:196) at com.sleepycat.je.log.ScavengerFileReader.processEntry(ScavengerFileReader.java:96) at com.sleepycat.je.log.FileReader.readNextEntryAllowExceptions(FileReader.java:340) at com.sleepycat.je.log.ScavengerFileReader.readNextEntry(ScavengerFileReader.java:117) at com.sleepycat.je.util.DbScavenger.scavengeDbTree(DbScavenger.java:208) at com.sleepycat.je.util.DbScavenger.dump(DbScavenger.java:163) at com.sleepycat.je.util.DbDump.main(DbDump.java:203)[#20385] (5.0.78)
transferMaster()
methods in the
ReplicatedEnvironment
class are provided for this
purpose. [#18081] (JE 5.0.64)
In one case, the master would become unable to accept any future group changes, even after all existing replicas were successfully connected and providing acknowledgements again. In another case the normal protections against duplicate masters could become compromised, making it possible (although unlikely) for transactions apparently "durably replicated" to a group majority to nevertheless disappear after a network partition were repaired. [#21095] (JE 5.0.64)
Also fixed a bug that caused a null key to be returned by DiskOrderedCursor.getNext. The bug occurred infrequently as the result of concurrent log cleaning activity. When it occurred, calling DatabaseEntry.getData for the key parameter would return null, even though DiskOrderedCursor.getNext returned OperationStatus.SUCCESS.
Thanks to Vinoth Chandar for reporting this on OTN, and helping us to diagnose the problem and test the fix.
[#21667] (JE 5.0.65)
java.lang.AssertionError: <ComplexType id="0" ... </ComplexType> at com.sleepycat.persist.impl.Evolver.evolveFormatInternal(Evolver.java:358) at com.sleepycat.persist.impl.Evolver.evolveFormat(Evolver.java:247) at com.sleepycat.persist.impl.ComplexFormat.evolveFieldList(ComplexFormat.java:1634) at com.sleepycat.persist.impl.ComplexFormat.evolveAllFields(ComplexFormat.java:1376) at com.sleepycat.persist.impl.ComplexFormat.evolve(ComplexFormat.java:1127) ...[#21869] (JE 5.0.66)
The log cleaner now outputs "No file selected for cleaning" log messages at
level FINE rather than at level INFO. (JE 5.0.66)
java.lang.AssertionError at com.sleepycat.je.tree.INTargetRep$Sparse.updateCacheStats(INTargetRep.java:296) at com.sleepycat.je.tree.INArrayRep.updateCacheStats(INArrayRep.java:133) at com.sleepycat.je.tree.INArrayRep.noteRepChange(INArrayRep.java:158) at com.sleepycat.je.tree.INArrayRep.noteRepChange(INArrayRep.java:163) at com.sleepycat.je.tree.INTargetRep$None.set(INTargetRep.java:331) at com.sleepycat.je.tree.INTargetRep$None.set(INTargetRep.java:303) at com.sleepycat.je.tree.IN.updateNode(IN.java:1498) at com.sleepycat.je.tree.IN.fetchTarget(IN.java:1332)This (like any assertion) would invalidate the Environment, but otherwise did not cause any persistent damage. [#21990] (5.0.70)
DbBackup.getLogFilesInSnapshot
. Calling this method rather than
File.list
is necessary to prevent the possibility that the log
cleaner will delete files prior to the creation of the backup manifest for the
current snapshot. If File.list
is called, as described previously
in the DbBackup
javadoc, the manifest may not contain the files
necessary for a restore and this would invalidate the backup. For more
information, see the updated description and examples at the top of the
DbBackup
class javadoc.
The code examples in the DbBackup
javadoc and the Getting Started
Guide have also been updated to pass the lastFileInPrevBackup
parameter to the DbBackup
constructor rather than to the
deprecated getLogFilesInBackupSet
method.
[#22014] (5.0.70)
121215 13:48:57:480 SEVERE [...] Average cleaner backlog has grown from 0.0 to 6.4. If the cleaner continues to be unable to make progress, the JE cache size and/or number of cleaner threads are probably too small. If this is not corrected, eventually all available disk space will be used.For more information on setting the cache size appropriately to avoid such problems, see: Why should the JE cache be large enough to hold the Btree internal nodes?
[#21111] (5.0.71)
Exception in thread "main" com.sleepycat.je.EnvironmentFailureException: (JE 5.0.XX) ... last LSN=.../... LOG_INTEGRITY: Log information is incorrect, problem is likely persistent. Environment is invalid and must be closed. at com.sleepycat.je.recovery.RecoveryManager.traceAndThrowException(RecoveryManager.java:2793) at com.sleepycat.je.recovery.RecoveryManager.undoLNs(RecoveryManager.java:1097) at com.sleepycat.je.recovery.RecoveryManager.buildTree(RecoveryManager.java:587) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:198) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:610) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:208) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:246) at com.sleepycat.je.Environment.[#22052] (5.0.71)(Environment.java:227) at com.sleepycat.je.Environment. (Environment.java:170) ... Caused by: java.lang.NullPointerException at com.sleepycat.je.log.entry.LNLogEntry.postFetchInit(LNLogEntry.java:406) at com.sleepycat.je.txn.TxnChain. (TxnChain.java:133) at com.sleepycat.je.txn.TxnChain. (TxnChain.java:84) at com.sleepycat.je.recovery.RollbackTracker$RollbackPeriod.getChain(RollbackTracker.java:1004) at com.sleepycat.je.recovery.RollbackTracker$Scanner.rollback(RollbackTracker.java:477) at com.sleepycat.je.recovery.RecoveryManager.undoLNs(RecoveryManager.java:1026) ... 10 more
Note that this change only applies to replicated environments. In non-replicated environments, deletion of log files has always been allowed (and is still allowed) in the portion of the log after the last application write.
[#21069] (5.0.71)
Also added a new cache statistic to help diagnose potential memory leaks: EnvironmentStats.getDataAdminBytes.
[#22100] (5.0.72)
Feb 11, 2013 3:32:13 PM com.sleepycat.je.utilint.DaemonThread run SEVERE:[#22202] (5.0.73)caught exception, java.lang.NullPointerException Continuing java.lang.NullPointerException at com.sleepycat.je.cleaner.FileProcessor.processLN(FileProcessor.java:808) at com.sleepycat.je.cleaner.FileProcessor.processFile(FileProcessor.java:674) at com.sleepycat.je.cleaner.FileProcessor.doClean(FileProcessor.java:289) at com.sleepycat.je.cleaner.FileProcessor.onWakeup(FileProcessor.java:148) at com.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:163) at java.lang.Thread.run(Thread.java:679)
Exception in thread "main" java.lang.NullPointerException at com.sleepycat.je.recovery.RecoveryManager.checkLogVersion8UpgradeViolations(RecoveryManager.java:2686) at com.sleepycat.je.recovery.RecoveryManager.buildTree(RecoveryManager.java:549) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:198) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:610) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:210) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:246) at com.sleepycat.je.Environment.[#22203] (5.0.73)(Environment.java:227) at com.sleepycat.je.Environment. (Environment.java:170) ...
WARNING: This fix could change the behavior of JE if a boolean EnvironmentConfig property is specified as "true" but with leading or trailing whitespace. Previously such a property would be set to false, and now it will be set to true.
[#22212] (5.0.73)
getNBINDeltasObsolete, getNBINDeltasCleaned, getNBINDeltasDead,
getNBINDeltasMigrated
.
Caused by: java.lang.AssertionError at com.sleepycat.je.txn.Txn.abortInternal(Txn.java:1127) at com.sleepycat.je.txn.Txn.abort(Txn.java:1094) at com.sleepycat.je.txn.Txn.abort(Txn.java:1067) at com.sleepycat.je.Transaction.abort(Transaction.java:205) ...If assertions are disabled and Transaction.abort() is called after InsufficientAcksException is thrown, the abort() will succeed (at least temporarily) on the master, but for a brief period (between the commit and the abort) may appear to other threads as committed. It will always be committed on the replicas. The abort() will be permanent on the master unless an abnormal shutdown and recovery occur and the transaction is replayed by recovery; in that case, the transaction will be committed on the master and the replicas.
To summarize, if Transaction.abort() is called after InsufficientAcksException is thrown and assertions are disabled, the transaction may be aborted on one node (the master at the time of the commit and abort), but committed on the other nodes (the replicas at the time). Otherwise, the only impact is that the transaction state will be wrong (it will be MUST_ABORT); in this case the transaction will be committed on all nodes.
The likelihood of the bug occurring in production is low because the InsufficientAcksException only occurs when a replica becomes unavailable in a small window. Normally, InsufficientReplicasException (which does not trigger this bug) is thrown when a replica is unavailable.
This bug was introduced in JE 5.0.48 and only applies to replicated environments. With the fix, the transaction state is correctly set to COMMITTED and the transaction will be committed on all nodes.
A workaround for this bug (an alternative to upgrading JE) is to be sure not to call abort() after commit(), at least when InsufficientAcksException is thrown. Calling abort() after commit() fails can make exception handling simpler, but is never necessary.
[#21598]
Environment.renameDatabase
, or
implicitly when a DPL Renamer
mutation is used to rename an entity
class or a secondary key field. This bug was introduced in JE 5.0.48. [#21537]
com.sleepycat.je.recovery.DirtyINMap.removeNextNode()
calling
java.util.HashMap$HashIterator.remove()
calling
java.util.HashMap.removeEntryForKey()
. [#21492]
DbVerify
to show a histogram of
BIN counts by utilization percentage.This is a sample of the output:
Verifying database p10 Checking tree for p10 BTree: Composition of btree, types and counts of nodes. binCount=3,207 binEntriesHistogram=[40-49%: 3,093; 50-59%: 10; 60-69%: 22; 70-79%: 26; 80-89%: 21; 90-99%: 35] binsByLevel=[level 1: count=3,207] deletedLNCount=0 inCount=49 insByLevel=[level 2: count=48; level 3: count=1] lnCount=209,716 mainTreeMaxDepth=3[#21106]
com.sleepycat.je.EnvironmentFailureException: (JE 5.0.34) Cannot log LNs in read-only env. UNEXPECTED_STATE: Unexpected internal state, may have side effects. at com.sleepycat.je.EnvironmentFailureException.unexpectedState(EnvironmentFailureException.java:376) at com.sleepycat.je.tree.LN.logInternal(LN.java:450) at com.sleepycat.je.tree.LN.optionalLog(LN.java:350) at com.sleepycat.je.dbi.CursorImpl.putCurrentAlreadyLatchedAndLocked(CursorImpl.java:1236) at com.sleepycat.je.dbi.CursorImpl.putCurrent(CursorImpl.java:1132) at com.sleepycat.je.dbi.DbTree$RewriteMapLN.doWork(DbTree.java:744) at com.sleepycat.je.tree.Tree.withRootLatchedExclusive(Tree.java:386) at com.sleepycat.je.dbi.DbTree.modifyDbRoot(DbTree.java:713) at com.sleepycat.je.dbi.DbTree.modifyDbRoot(DbTree.java:646) at com.sleepycat.je.dbi.DbTree.optionalModifyDbRoot(DbTree.java:636) at com.sleepycat.je.tree.Tree.searchSplitsAllowed(Tree.java:1217) at com.sleepycat.je.tree.Tree.getParentBINForChildLN(Tree.java:817) at com.sleepycat.je.recovery.RecoveryManager.redo(RecoveryManager.java:1911) at com.sleepycat.je.recovery.RecoveryManager.redoOneLN(RecoveryManager.java:1502) at com.sleepycat.je.recovery.RecoveryManager.redoLNs(RecoveryManager.java:1302) at com.sleepycat.je.recovery.RecoveryManager.buildTree(RecoveryManager.java:586) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:188) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:604) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:210) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:246) at com.sleepycat.je.Environment.Note that the exception occurs before the Environment constructor returns. [#21493](Environment.java:227) at com.sleepycat.je.Environment. (Environment.java:170) ...
JoinCursor
that causes records to be incorrectly
passed over (not returned) when the cursors are configured for read-uncommitted
isolation mode, and a non-null data
parameter is passed to
JoinCursor.getNext
. Thanks to Arthur Brack for reporting this,
debugging it, and telling us how to fix it! [#21501]
com.sleepycat.je.recovery.Checkpointer.wakeupAfterWrite
method.
[#21106]
InsufficientAcksException
even if it had been configured
as Designated Primary, if it happened to lose the connection to the
replica in the middle of waiting for the commit acknowledgement.
[#21536]
com.sleepycat.je.EnvironmentFailureException: Environment invalid because of previous exception: (JE 5.0.34) fetchTarget of 0xc3d4/0x25dab parent IN=2372138 IN class=com.sleepycat.je.tree.IN lastFullVersion=0xc4ca/0xd2aad lastLoggedVersion=0xc4ca/0xd2aad parent.getDirty()=false state=0 LOG_FILE_NOT_FOUND: Log file missing, log is likely invalid. Environment is invalid and must be closed. ...The bug occurred after deleting a range of keys in a deferred-write database (DatabaseConfig.setDeferredWrite(true) or StoreConfig.setDeferredWrite(true)), closing the Environment, and then opening the Environment. It is most likely to occur when deleting large numbers of consecutive keys, and when opening and closing the Environment often, with the log cleaner enabled.
Because a log file is incorrectly deleted as a result of this bug, restoring from a backup is necessary, i.e., there is no way to repair the environment. Many thanks to Vishal Vishnoi and Vladimir Egorov for reproducing the problem and helping us to diagnose it.
[#21348]
com.sleepycat.je.EnvironmentFailureException: Environment invalid because of previous exception: (JE 5.0.34) fetchTarget of 0x1ced/0x3d3561b parent IN=116781 IN class=com.sleepycat.je.tree.BIN lastFullVersion=0xbc40/0x2ca3f3a lastLoggedVersion=0xbcc3/0x6a37712 parent.getDirty()=false state=0 LOG_FILE_NOT_FOUND: Log file missing, log is likely invalid. Environment is invalid and must be closed. ...The bug occurred when a preload (Database.preload or Environment.preload) was performed concurrently with other access to the database, including log cleaning. For example, the bug could occur as a result of the following sequence:
Because a log file is incorrectly deleted as a result of this bug, restoring from a backup is necessary, i.e., there is no way to repair the environment. We are in Diego's debt for not only reporting this bug on OTN, but for reproducing it repeatedly for us over an extended period of debugging, and finally testing the fix.
[#21319]
DatabaseConfig.setBtreeComparator
or
DatabaseConfig.setDuplicateComparator
, or by implementing the
Comparable
interface in a DPL key class.
DatabaseConfig.setKeyPrefixing(true)
and is enabled by default
for all databases configured for duplicates. A database is configured for
duplicates explicitly using
DatabaseConfig.setSortedDuplicates(true)
, or implicitly using
a DPL MANY_TO_XXX relationship (Relationship.MANY_TO_ONE
or
Relationship.MANY_TO_MANY
).
Thanks to Lee Saenz and the other folks at UnboundId for reporting this problem and reproducing it repeatedly for us during debugging.
[#21328]
Fixed a bug in the DbPreUpgrade_4_1 and DbRepPreUpgrade_4_1 utilities that prevented them from working properly due to concurrent log cleaning activity while the utility is running. The symptom of the bug is that, after running the utility without errors, when then opening the Environment with JE 5, the following exception would occur:
com.sleepycat.je.EnvironmentFailureException: (JE 5.0.XX) Before upgrading to JE 5.0, the following utility must be run using JE 4.1: DbPreUpgrade_4_1 using the JE old version. See the release notes.WARNING: Due to this bug, JE 4.1.20 or later should be used to run the DbPreUpgrade_4_1 and DbRepPreUpgrade_4_1 utilities. In addition, these utilities should be run for all environments, not just those with duplicates databases. See "Upgrade Procedure" above for information on running these utilities.
Thanks to Vinoth for reporting the problem and helping us with the diagnosis and testing. [#21304]
java.lang.ArrayIndexOutOfBoundsException at com.sleepycat.je.dbi.DupKeyData$TwoPartKeyComparator.compare(DupKeyData.java:200) at com.sleepycat.je.dbi.DupKeyData$TwoPartKeyComparator.compare(DupKeyData.java:167) at com.sleepycat.je.tree.Key.compareKeys(Key.java:187) at com.sleepycat.je.tree.IN.findEntry(IN.java:2205) at com.sleepycat.je.tree.Tree.searchSubTreeInternal(Tree.java:1414) at com.sleepycat.je.tree.Tree.searchSubTree(Tree.java:1310) at com.sleepycat.je.tree.Tree.search(Tree.java:1170) at com.sleepycat.je.cleaner.FileProcessor.processBINDelta(FileProcessor.java:1075) at com.sleepycat.je.cleaner.FileProcessor.processFile(FileProcessor.java:625) at com.sleepycat.je.cleaner.FileProcessor.doClean(FileProcessor.java:290) at com.sleepycat.je.cleaner.FileProcessor.onWakeup(FileProcessor.java:149) at com.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:162) at java.lang.Thread.run(Thread.java:662)Also fixed a bug that could result in an exception similar to the above:
java.lang.ArrayIndexOutOfBoundsException at com.sleepycat.je.dbi.DupKeyData$TwoPartKeyComparator.compare(DupKeyData.java:200) at com.sleepycat.je.dbi.DupKeyData$TwoPartKeyComparator.compare(DupKeyData.java:167) at com.sleepycat.je.tree.Key.compareKeys(Key.java:188) at com.sleepycat.je.tree.IN.findEntry(IN.java:2247) at com.sleepycat.je.tree.IN.findEntry(IN.java:2168) at com.sleepycat.je.tree.IN.findParent(IN.java:3082) at com.sleepycat.je.tree.Tree.getParentINForChildIN(Tree.java:773) at com.sleepycat.je.tree.Tree.getParentINForChildIN(Tree.java:704) at com.sleepycat.je.cleaner.FileProcessor.findINInTree(FileProcessor.java:1228) at com.sleepycat.je.cleaner.FileProcessor.processIN(FileProcessor.java:1167) at com.sleepycat.je.cleaner.FileProcessor.processFile(FileProcessor.java:650) at com.sleepycat.je.cleaner.FileProcessor.doClean(FileProcessor.java:290) at com.sleepycat.je.cleaner.FileProcessor.onWakeup(FileProcessor.java:149) at com.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:162) at java.lang.Thread.run(Thread.java:722)This problem was originally reported on OTN. [#21405]
Environment.removeDatabase
or
truncateDatabase
to loop in a "livelock" pattern along with active
log cleaner threads, where the removeDatabase
or
truncateDatabase
thread is not making forward progress. Also fix
a bug that could cause this state to eventually cause an
EnvironmentFailureException
during a subsequent recovery, and
prevent opening the environment. [#20816]
Environment.checkpoint
or Environment.close
to hang with the following stack
trace. The can only happen in a replicated environment, and the most
realistic situation that could provoke this is a call to
Environment.close() while there are ongoing, concurrent write
operations.
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:253) at com.sleepycat.je.rep.vlsn.VLSNIndex.waitForVLSN(VLSNIndex.java:544) at com.sleepycat.je.rep.vlsn.VLSNIndex.awaitConsistency(VLSNIndex.java:1982) at com.sleepycat.je.rep.impl.RepImpl.awaitVLSNConsistency(RepImpl.java:1644) at com.sleepycat.je.recovery.Checkpointer.doCheckpoint(Checkpointer.java:726) at com.sleepycat.je.dbi.EnvironmentImpl.invokeCheckpoint(EnvironmentImpl.java:1938) at com.sleepycat.je.dbi.EnvironmentImpl.doClose(EnvironmentImpl.java:1644)[#20919]
com.sleepycat.je.rep.ReplicationConfig.REPLICA_RECEIVE_BUFFER_SIZE
parameter controls the buffer size of the TCP connection used to communicate changes
between a replica and its master.
setReceiveBufferSize(int)
and
getReceiveBufferSize()
methods of the class
com.sleepycat.je.rep.NetworkRestore
are used when copying
log files between replication nodes for Network Restore.
java.lang.AssertionError at com.sleepycat.persist.impl.RecordInput.readObject(RecordInput.java:150) at com.sleepycat.persist.impl.ReflectionAccessor$ObjectAccess.read(ReflectionAccessor.java:442) at com.sleepycat.persist.impl.ReflectionAccessor.readNonKeyFields(ReflectionAccessor.java:300) at com.sleepycat.persist.impl.ComplexFormat$EvolveReader.readObject(ComplexFormat.java:2218) at com.sleepycat.persist.impl.PersistEntityBinding.readEntity(PersistEntityBinding.java:163) at com.sleepycat.persist.impl.PersistEntityBinding.entryToObjectInternal(PersistEntityBinding.java:107) at com.sleepycat.persist.impl.PersistEntityBinding.entryToObject(PersistEntityBinding.java:64) at com.sleepycat.persist.EntityValueAdapter.entryToValue(EntityValueAdapter.java:55) ...[#21078]
Environment.removeDatabase
and truncateDatabase
(see
[#20816] above). The additional fixes address long operation times due to log
cleaning with large file sizes in combination with eviction. Also fix a bug
that slows down log cleaning (contributing to the long operation times as well)
when large numbers of databases are present, and not all databases are kept
open by the application. [#21015]
java.lang.NullPointerException com.sleepycat.je.tree.IN.get3ByteInt(IN.java:1251) com.sleepycat.je.tree.IN.getFileOffset(IN.java:1241) com.sleepycat.je.tree.IN.getLsn(IN.java:1039) com.sleepycat.je.cleaner.Cleaner.isEvictable(Cleaner.java:1117) com.sleepycat.je.tree.BIN.getChildEvictionType(BIN.java:337) com.sleepycat.je.tree.IN.getEvictionType(IN.java:3146) com.sleepycat.je.evictor.TargetSelector.selectIN(TargetSelector.java:129) com.sleepycat.je.evictor.Evictor.evictBatch(Evictor.java:612) ...[#21015]
com.sleepycat.je.EnvironmentFailureException: (JE 5.0.34) com.sleepycat.je.utilint.RelatchRequiredException UNEXPECTED_EXCEPTION: Unexpected internal Exception, may have side effects. at com.sleepycat.je.EnvironmentFailureException.unexpectedException(EnvironmentFailureException.java:286) at com.sleepycat.je.tree.BIN.fetchTarget(BIN.java:1268) at com.sleepycat.je.Cursor.checkForInsertion(Cursor.java:3006) at com.sleepycat.je.Cursor.retrieveNextAllowPhantoms(Cursor.java:2926) at com.sleepycat.je.Cursor.retrieveNextNoDups(Cursor.java:2789) at com.sleepycat.je.Cursor.retrieveNext(Cursor.java:2763) at com.sleepycat.je.Cursor.getNext(Cursor.java:1116) ...Thanks to OTN user user591209 for reporting this and testing the fix. [#21121]
ReplicationConfig.REPLAY_MAX_OPEN_DB_HANDLES
and
ReplicationConfig.REPLAY_DB_HANDLE_TIMEOUT
have been
deprecated. Please use the mutable configuration parameters:
ReplicationMutableConfig.REPLAY_MAX_OPEN_DB_HANDLE
and
ReplicationMutableConfig.REPLAY_DB_HANDLE_TIMEOUT
instead. This
change also fixes a bug which resulted in the values associated with these
parameters being used incorrectly.
[#21144]
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 115 in method com.sleepycat.persist.impl.CollectionProxy.copyElements (Lcom/sleepycat/persist/impl/RecordInput;Lcom/sleepycat/persist/impl/Format; Lcom/sleepycat/persist/impl/Format;Ljava/util/Set;)V at offset 33 at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at com.sleepycat.persist.model.EntityModel.classForName(EntityModel.java:280) at com.sleepycat.persist.model.AnnotationModel.getClassMetadata(AnnotationModel.java:91) at com.sleepycat.persist.impl.PersistCatalog.addProxiedClass(PersistCatalog.java:528) at com.sleepycat.persist.impl.PersistCatalog.init(PersistCatalog.java:399) at com.sleepycat.persist.impl.PersistCatalog.This issue did not normally arise when using a downloaded JE jar file, because the JE library is compiled with a Java 1.5 bytecode target. It would arise, however, if JE were explicitly compiled with a Java 1.7 bytecode target, or with Java 1.7 and no specified target. A workaround for this issue was to specify -XX:-UseSplitVerifier when running Java; this is no longer necessary. [#20586](PersistCatalog.java:218) at com.sleepycat.persist.impl.Store. (Store.java:177) at com.sleepycat.persist.EntityStore. (EntityStore.java:111)
java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) at com.sleepycat.je.Environment.checkOpenTxns(Environment.java:469) at com.sleepycat.je.Environment.checkForCloseErrors(Environment.java:409) at com.sleepycat.je.Environment.close(Environment.java:368)Although never reported, a similar problem could occur if Databases are open. [#21279]
Transaction.getState()
method and
Transaction.State
enumeration to formalize the different states of
a transaction, and in particular to indicate whether a transaction commit is in
an undetermined state (Transaction.State.POSSIBLY_COMMITTED
) when
a failure occurs during the commit process. Also added an internal pre-flight
check, just before making a commit durable, to narrow the time window where the
Transaction.State.POSSIBLY_COMMITTED
state can occur. See the new
javadoc for more details. [#21264]
EnvironmentConfig.EVICTOR_CRITICAL_PERCENTAGE
. This
parameter can be set to improve operation latency under certain conditions.
See the javadoc for more information.
Also improved eviction to avoid acquiring a per-database exclusive latch for each Btree node that is evicted. This appeared in thread dumps as follows:
"JEEvictor" daemon prio=3 tid=0x000000000a28e000 nid=0x197 waiting on condition [0xfffffc7fcd8b8000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0xfffffc701242b048> (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178) at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:807) at com.sleepycat.je.latch.SharedLatch.acquireExclusive(SharedLatch.java:95) at com.sleepycat.je.latch.SharedLatch.acquireShared(SharedLatch.java:135) at com.sleepycat.je.tree.IN.latchShared(IN.java:484) at com.sleepycat.je.tree.Tree.searchSubTreeInternal(Tree.java:1508) at com.sleepycat.je.tree.Tree.searchSubTree(Tree.java:1329) at com.sleepycat.je.tree.Tree.search(Tree.java:1189) at com.sleepycat.je.dbi.CursorImpl.searchAndPosition(CursorImpl.java:2064) at com.sleepycat.je.dbi.CursorImpl.searchAndPosition(CursorImpl.java:1983) at com.sleepycat.je.dbi.DbTree.getDb(DbTree.java:1535) at com.sleepycat.je.dbi.DbTree.getDb(DbTree.java:1471) at com.sleepycat.je.dbi.DbTree.getDb(DbTree.java:1459) at com.sleepycat.je.evictor.Evictor.evictBatch(Evictor.java:633) at com.sleepycat.je.evictor.Evictor.doEvict(Evictor.java:542) at com.sleepycat.je.evictor.Evictor$BackgroundEvictTask.run(Evictor.java:1205) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)Thanks to Jerome Arnou for diagnosing this issue. [#21106]
... com.sleepycat.je.latch.SharedLatch.acquireExclusive(SharedLatch.java:95) com.sleepycat.je.tree.IN.latch(IN.java:473) com.sleepycat.je.tree.IN.latch(IN.java:508) com.sleepycat.je.tree.BIN.containsCursor(BIN.java:467) com.sleepycat.je.dbi.CursorImpl.setBIN(CursorImpl.java:386) com.sleepycat.je.tree.Tree.findBinForInsert(Tree.java:2198) ...Thanks to Arthur Brack for reporting this issue. [#21395]
A DiskOrderedCursor can be obtained via
Database.openCursor(DiskOrderedCursorConfig)
. Note that
creating an instance of the DiskOrderedCursor disables the file
deletion done by log cleaning until the close()
method
has been called. See the javadoc for DiskOrderedCursor for more
detailed information. [#15260]
Environment.preload(Databases[], PreloadConfig)
method has been added which permits preloading multiple databases
via a single method call rather than multiple calls
to Database.preload()
.
Preload is implemented to optimize I/O cost by fetching the records of a Database by disk
order, so that disk access is are sequential rather than
random. Using the multi-database Environment.preload()
lets the preload operation batch
the records for all of the target Databases so that
multiple scans over the log are not necessary.
A progress mechanism has also been added which lets a caller of
the preload()
method receive feedback on whether progress
is being made. See
com.sleepycat.je.ProgressListener
and
com.sleepycat.je.PreloadConfig.setProgressListener()
.
Two new configurations are available to bound the amount of memory
used by preload processing, at the expense of preload
performance. com.sleepycat.je.PreloadConfig.setLSNBatchSize()
can be used to direct preload to partition its work into batches., In
addition, com.sleepycat.je.PreloadConfig.setInternalMemoryLimit()
can be used to limit the amount of memory outside of the JE cache used
by preload.
[#15260] [#18153] [#19306]
Environment subdirectories are enabled through
the je.log.nDataDirectories
environment parameter. If 0
(the default), all log files (*.jdb) will reside in the environment
home directory passed to the Environment constructor. A non zero
value indicates the number of environment subdirectories to use for
holding the environment's log files.
If data subdirectories are used (i.e. je.log.nDataDirectories > 0), this parameter must be set when the environment is initially created. Like the environment home directory, each and every one of the dataNNN/ subdirectories must also be present and writable. This parameter must be set to the same value for all subsequent openings of the environment or an exception will be thrown.
If the set of existing dataNNN/ subdirectories is not equivalent to the set { 1 ... je.log.nDataDirectories } when the environment is opened, an EnvironmentFailureException will be thrown, and the Environment will fail to be opened.
DbBackup.getLogFilesInBackupSet()
now returns the subdirectory
name and file separator prepended to the file name if
je.log.nDataDirectories > 0. [#19125]
Cursor.skipNext
and Cursor.skipPrev
. [#19165]
EnvironmentConfig.setClassLoader
. Related changes are:
com.sleepycat.util.ClassResolver
class defines
and implements the class loading policy.com.sleepycat.je.DatabaseComparator
interface.com.sleepycat.bind.serial.Catalog
interface has a
new method, getClassLoader
, that is used to supply the
ClassLoader to the SerialBinding
. This method is
implemented by the StoredClassCatalog
class, and returns
the environment's ClassLoader property. As a result,
SerialBinding.getClassLoader
now returns the environment's
ClassLoader property.
com.sleepycat.persist.model.EntityModel.classForName
static method has been deprecated in favor of the new
EntityModel.resolveClass
method, which honors the
environment's ClassLoader property.java.io.Closeable
interface is now implemented by all JE
classes and interfaces with a public void close()
method. This
allows using these objects with the Java 1.7 try-with-resources statement, for
applications compiled and run with Java 1.7 or later. See
AutoCloseable,
which is a superinterface of java.io.Closeable
in Java 1.7.
The following JE classes and interfaces now implement Closeable
,
and on Java 1.7 AutoCloseable
.
com.sleepycat.bind.serial.ClassCatalog com.sleepycat.bind.serial.StoredClassCatalog com.sleepycat.collections.StoredIterator com.sleepycat.persist.EntityCursor com.sleepycat.persist.EntityJoin com.sleepycat.persist.EntityStore com.sleepycat.persist.ForwardCursor com.sleepycat.persist.raw.RawStore com.sleepycat.je.jca.ra.JEConnection com.sleepycat.je.Cursor com.sleepycat.je.Database com.sleepycat.je.DiskOrderedCursor com.sleepycat.je.Environment com.sleepycat.je.ForwardCursor com.sleepycat.je.JoinCursor com.sleepycat.je.SecondaryDatabase com.sleepycat.je.Sequence com.sleepycat.je.trigger.Trigger[#20559]
Environment.flushLog
method has been added. It can be used to
make durable, by writing to the log, all preceding non-transactional write
operations, as well as any preceding transactions that were committed with
no-sync durability. To flush buffered data for durability reasons, with the
addition of this method it is no longer necessary to perform a checkpoint, call
Environment.sync
, or commit a transaction (with sync or
write-no-sync durability). [#19111]
EnvironmentConfig.TXN_DEADLOCK_STACK_TRACE
for debugging.
je.env.fairLatches
environment parameter has been deprecated
and no longer has any effect.
EnvironmentConfig.CHECKPOINTER_BYTES_INTERVAL
has changed.
Previously, this interval defined the byte distance between the end of one
checkpoint and the start of the next. Now it defines the byte distance between
the start of one checkpoint and start of the next. In other words, now the
interval includes the checkpoint itself, which in some cases can be large.
This now more accurately reflects the intention of the parameter, which is to
bound the recovery interval, which is proportional to the time to recover (open
the Environment
) after a crash. It does mean, however, that
checkpoints may occur more often for the same configured interval, and some
applications may wish to adjust their configured setting accordingly. [#19704]
Cursor.getSearchBothRange
for a non-duplicates database has been
corrected to behave exactly as Cursor.getSearchBoth
. Previously
getSearchBothRange
returned a data item that was greater or equal
to the data search parameter, which was incorrect. Now it only returns a data
item that is equal to the data search parameter. [#19165]
EnvironmentConfig.CLEANER_LAZY_MIGRATION
has
been changed from true to false. Over several releases the benefits of setting
this to true have decreased and are now less than the benefits of setting it to
false. See the javadoc for this parameter for details. [#20588]
As a result of this change, the log cleaner must now sometimes estimate the
size of records that are made obsolete by updates and deletions, and must
sometimes "probe" a log file to determine record sizes. Several statistics
have been added to show this activity in the
com.sleepycat.je.EnvironmentStats
class:
getCorrectedAvgLNSize
getEstimatedAvgLNSize
getNCleanerProbeRuns
DbSpace
utility now also prints the first two of these new
statistics.
[#18633]
Internal Format Change
This information is included for users who understand Btree internals and wish to know what changed internally.
Performance Improvements
Other Behavioral Changes
DatabaseConfig.setKeyPrefixing(true)
. If
DatabaseConfig.setKeyPrefixing(false)
is called for a database
with duplicates configured, an IllegalStateException
is
thrown.
Cursor.count
) is more costly than it was previously.
Previously, the count was stored and could be returned by reading a single
record for the key. Now, to determine the count precisely JE must traverse
internal Btree nodes to count the duplicates for the key. If you are using
Cursor.count
, consider using the new method
Cursor.countEstimate
instead.
Cursor.countEstimate
returns a rough estimate of the count
using a fixed cost algorithm. Since Cursor.count
is primarily
intended for use in query optimizations, the
Cursor.countEstimate
method may be a good substitute. For
example, JoinCursor
now uses Cursor.countEstimate
rather than Cursor.count
to determine the index processing
order. Likewise, EntityCursor.countEstimate
is a potential
substitute for EntityCursor.count
. DatabaseConfig.setBtreeComparator
for
information on partial comparators. Previously, Btree partial comparators
could be use only with non-duplicate databases.
DatabaseConfig.setNodeMaxDupTreeEntries
DatabaseConfig.getNodeMaxDupTreeEntries
BtreeStats.getDuplicateBottomInternalNodeCount
BtreeStats.getDupCountLeafNodeCount
BtreeStats.getDuplicateInternalNodeCount
BtreeStats.getDuplicateTreeMaxDepth
BtreeStats.getDINsByLevel
BtreeStats.getDBINsByLevel
PreloadStats.getNDINsLoaded
PreloadStats.getNDBINsLoaded
PreloadStats.getNDupCountLNsLoaded
Previously, delta log entries for bottom internal nodes, called BINDeltas, were
written by checkpoints rather than writing full BINs, and full BINs were
written less frequently (see EnvironmentConfig.TREE_MAX_DELTA
and
TREE_BIN_DELTA
). This is still the case. However, the approach
taken previously required that the same delta information be repeatedly written
at each checkpoint, even it had not changed since the last checkpoint. Now,
delta information is only written when it changes.
By significantly reducing writing, the new approach provides overall performance improvements. However, there is also an additional cost to the new approach: When a BIN is not in cache, fetching the BIN now often requires two random reads instead of just one; one read to fetch the BINDelta and another to fetch the last full BIN. For applications where all active BINs fit in cache, this adds to the I/O cost of initially populating the cache. For applications where active BINs do not fit in cache, this adds to the per-operation cost of fetching a record (an LN) when its parent BIN is not in cache. In our tests, the lower write rate more than compensates for the additional I/O of fetching the BINDelta, but the benefit is greatest when all BINs fit in cache.
[#19671]
CheckpointConfig.setMinimizeRecoveryTime(true)
is used
along with an explicit checkpoint performed by calling the
Environment.checkpoint
method.Environment.sync
is called.Environment.close
is called, since it performs a final
checkpoint.Environment.checkpoint
) would
cause long recovery times under certain circumstances.
As a part of this work, the actions invoked by ReplicatedEnvironment.shutdownGroup() were streamlined to use the setMinimizeRecoveryTime() option and to reduce spurious timeouts during the shutdown processing. [#19559]
DatabaseConfig.setNodeMaxEntries
s) are now
mutable and persistent database attributes. They were previously permitted to
mutate, but the changed attribute value wasn't saved persistently, so the new
value might sometimes revert to the previously existing setting. This has been
fixed. In addition, the javadoc for DatabaseConfig has been expanded to
clarify what attributes are mutable vs. fixed, persistent vs temporary.
[#18262]
Implementation-Title
, Implementation-Version
,
Implementation-Vendor
, Implementation-URL
entries to
the je.jar MANIFEST.MF
file. [#19320]
"Cleaner-5" daemon prio=10 tid=0x00002aaae8008800 nid=0xaeb runnable [0x0000000042ac9000] java.lang.Thread.State: RUNNABLE at com.sleepycat.je.cleaner.OffsetList.contains(OffsetList.java:132) at com.sleepycat.je.cleaner.TrackedFileSummary.containsObsoleteOffset(TrackedFileSummary.java:169) at com.sleepycat.je.cleaner.FileProcessor.processFile(FileProcessor.java:495) at com.sleepycat.je.cleaner.FileProcessor.doClean(FileProcessor.java:243) locked <0x00002aaab0652408> (a com.sleepycat.je.cleaner.FileProcessor) at com.sleepycat.je.cleaner.FileProcessor.onWakeup(FileProcessor.java:140) at com.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:162) at java.lang.Thread.run(Thread.java:662)[#19626]
EnvironmentConfig.TREE_COMPACT_MAX_KEY_LENGTH
for user
configuration of the in-memory compaction of keys in the Btree. Previously,
in-memory keys were compacted but the key size threshold was fixed at 16 bytes.
Now the key size threshold is configurable and has a 16 byte default value.
For more information, see the
EnvironmentConfig.TREE_COMPACT_MAX_KEY_LENGTH
javadoc. [#20120]
Database
handle kept a reference to the
environment after it was closed. Added the following warning to the
close()
method javadoc for all JE handles.
WARNING: To guard against memory leaks, the application should discard all references to the closed handle. While BDB makes an effort to discard references from closed objects to the allocated memory for an environment, this behavior is not guaranteed. The safe course of action for an application is to discard all references to closed BDB objects.[#20302]
The fix changes the final step above so that an election is held before the rollback is allowed to proceed. The election results in C being elected the new master. Node A encounters a MasterReplicaTransitionException which it must handle by closing and re-opening its environment handle so it can resume operations as a replica. [#20258] [#20572]
FileProcessor.processFoundLN
. This only occurs when temporary
databases are used and Environment.CLEANER_LAZY_MIGRATION
is set
to false, which is now the default in JE 5. [#20670]
(JE 5.0.30) node2(2):/tmp/scaleDir2/env Couldn't find bucket for GTE VLSN 299,617,391 in database. EndBucket =[#20726]tracker = first=298,966,283 last=299,617,477 sync=299,617,458 txnEnd=299,617,458 firstTracked=-1 lastOnDiskVLSN=299,617,477 UNEXPECTED_STATE_FATAL: Unexpected internal state, unable to continue. Environment is invalid and must be closed. at com.sleepycat.je.EnvironmentFailureException.unexpectedState(EnvironmentFailureException.java:391) at com.sleepycat.je.rep.vlsn.VLSNIndex.getGTEBucketFromDatabase(VLSNIndex.java:911) at com.sleepycat.je.rep.vlsn.VLSNIndex.getGTEBucket(VLSNIndex.java:780) at com.sleepycat.je.rep.vlsn.VLSNIndex.access$000(VLSNIndex.java:308) at com.sleepycat.je.rep.vlsn.VLSNIndex$ForwardVLSNScanner.getLsn(VLSNIndex.java:2119) at com.sleepycat.je.rep.vlsn.VLSNIndex$ForwardVLSNScanner.getApproximateLsn(VLSNIndex.java:2081) at com.sleepycat.je.rep.stream.FeederReader.scanForwards(FeederReader.java:224) at com.sleepycat.je.rep.stream.MasterFeederSource.getWireRecord(MasterFeederSource.java:62) at com.sleepycat.je.rep.impl.node.Feeder$OutputThread.run(Feeder.java:762)
java.lang.IndexOutOfBoundsException: Index: 110, Size: 110 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at com.sleepycat.je.rep.vlsn.VLSNBucket.findPopulatedIndex(VLSNBucket.java:441) at com.sleepycat.je.rep.vlsn.VLSNBucket.removeFromTail(VLSNBucket.java:730) at com.sleepycat.je.rep.vlsn.VLSNIndex.pruneDatabaseTail(VLSNIndex.java:1087) at com.sleepycat.je.rep.vlsn.VLSNIndex.merge(VLSNIndex.java:1274) at com.sleepycat.je.rep.vlsn.VLSNIndex.init(VLSNIndex.java:1161) at com.sleepycat.je.rep.vlsn.VLSNIndex.There was no corruption to the persistent data, but without this fix, the environment would repeatedly fail to open. [#20796](VLSNIndex.java:382) at com.sleepycat.je.rep.impl.RepImpl.preRecoveryCheckpointInit(RepImpl.java:374) at com.sleepycat.je.recovery.RecoveryManager.recover(RecoveryManager.java:238) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit(EnvironmentImpl.java:549) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:237) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:229) at com.sleepycat.je.Environment. (Environment.java:211) at com.sleepycat.je.Environment. (Environment.java:176) at com.sleepycat.je.rep.ReplicatedEnvironment. (ReplicatedEnvironment.java:443) at com.sleepycat.je.rep.ReplicatedEnvironment. (ReplicatedEnvironment.java:318) at com.sleepycat.je.rep.ReplicatedEnvironment. (ReplicatedEnvironment.java:379)
DatabaseConfig.setKeyPrefixing
) was
not effective when keys are inserted in sequential order, for example, during a
bulk load in key order. Without any updates, deletions or non-sequential
insertions, the prefix information was not persistent and therefore not used
after closing and re-opening the Environment. In addition, during sequential
insertion more cache space than necessary was used under certain circumstances.
These problems did not occur with non-sequential insertion. [#20799]
DbCacheSize
utility to take into account memory
management enhancements and improve accuracy. Added support for key prefixing
(-keyprefix
), databases configured for sorted duplicates
(-duplicates
), and replicated environments
(-replicated
). Environment config params and replication config
params may also be specified, since they impact memory usage as well.
The old -density
argument has been replaced by
-orderedinsertion
. The old -overhead
argument has
been removed, and the utility prints the minimum environment memory overhead.
See the DbCacheSize
javadoc for more information. It now includes
a discussion of how cache memory is used and how it can be reduced using
environment and database configuration options. [#20145]
SecondaryCursor
method that moves the cursor to an existing
record. This occurs when both of the following conditions are true:
com.sleepycat.bind.tuple.SortedPackedIntegerBinding
-- new classcom.sleepycat.bind.tuple.SortedPackedLongBinding
-- new classcom.sleepycat.bind.tuple.TupleInput
-- new methods: readSortedPackedInt, getSortedPackedIntByteLength, readSortedPackedLong, getSortedPackedLongByteLength
.com.sleepycat.bind.tuple.TupleOutput
-- new methods: writeSortedPackedInt, writeSortedPackedLong
.com.sleepycat.util.PackedInteger
-- new methods: readSortedInt, readSortedLong, getReadSortedIntLength, getReadSortedLongLength, writeSortedInt, writeSortedLong, getWriteSortedIntLength, getWriteSortedLongLength
.See the com.sleepycat.bind.tuple
package description for an
overview of the new bindings and a comparative description of all tuple
bindings. [#18379]
java.math.BigDecimal
data type are now
available.
BigDecimal
values in record
keys, and provides natural sort order without a custom comparator. The API
additions are:com.sleepycat.bind.tuple.SortedBigDecimalBinding
-- new classcom.sleepycat.bind.tuple.TupleInput
-- new methods: readSortedBigDecimal, getSortedBigDecimalByteLength
.com.sleepycat.bind.tuple.TupleOutput
-- new methods: writeSortedBigDecimal, getSortedBigDecimalMaxByteLength
.BigDecimal
format does not provide natural
sort order and is not intended for use in record keys, but has two
advantages over the sorted format: trailing zeros after the decimal place
are preserved, and a more compact, faster serialization format is used.
The API additions are:com.sleepycat.bind.tuple.BigDecimalBinding
-- new classcom.sleepycat.bind.tuple.TupleInput
-- new methods: readBigDecimal, getBigDecimalByteLength
.com.sleepycat.bind.tuple.TupleOutput
-- new methods: writeBigDecimal, getBigDecimalMaxByteLength
.See the com.sleepycat.bind.tuple
package description for an
overview of the new bindings and a comparative description of all tuple
bindings. [#18379]
java.math.BigDecimal
is now defined as a built-in DPL simple data
type. This means that BigDecimal
values may be stored in DPL
persistent objects, and fields of type BigDecimal
may be defined
as primary or secondary keys. The sorted BigDecimal
format is
always used in the DPL, and this provides natural sort order without a custom
comparator. However, trailing zeros after the decimal place are stripped,
meaning that precision is not preserved.
If the application has previously defined a PersistentProxy
for
BigDecimal
, special considerations are necessary when upgrading
to this release:
EntityModel.registerClass
for the
BigDecimal
proxy class must be removed. If it is not removed,
an IllegalArgumentException
will be thrown by the
EntityStore
constructor. In general, proxies for built-in
simple types are not allowed.
BigDecimal
proxy class is not registered, the
proxy class must be available for reading BigDecimal
values
that were written via the proxy, prior to this release.
Rewriting (updating) an entity will convert the proxied
BigDecimal
value to the new built-in BigDecimal
format. To convert all entities explicitly and efficiently, the
EntityStore.evolve
method may be used.
After converting all entities using the proxied values, if you additionally
wish to remove the proxy class itself then you must supply a
Deleter
mutation for the proxy class.
BigDecimal
proxy class, as a secondary key, the application
must first explicitly evolve the index using
EntityStore.evolve
, or update all values. Then the
@SecondaryKey
annotation may be added to create a new
secondary index.
[#18379]
java.util.LinkedHashMap
. LinkedHashMap
may now be
used as the type of any persistent field. [#20055]
MANY_TO_ONE
and MANY_TO_MANY
secondary index ordering when a Comparable
key class is used for
the primary key.
In general, for MANY_TO_ONE
and MANY_TO_MANY
secondary indexes, more than one entity may have the same secondary key. When
iterating over entities in secondary key order, the ordering of entities is by
primary key within secondary key. For example, if Employee entities with an
integer ID primary key are iterated using a String department secondary key,
the iteration order is by integer ID within (grouped by) department.
In prior releases, when a Comparable
key class is used for the
primary key, the Comparable
defines the order of entities in the
primary index. However, the Comparable.compareTo
method is not
used to determine primary key ordering within secondary key. Instead, the
natural order of the primary keys is used. In our example, if the primary key
class implements Comparable
to order entities in decreasing
integer order, the iteration order is incorrectly in natural integer order
(increasing) within department. This has been fixed and the order for newly
created secondary indexes now uses the Comparable
, and in our
example the iteration order is now decreasing integer order within
department.
However, because the ordering of an existing index cannot be changed, the
old ordering will apply for secondary indexes created prior to this release.
To cause the correct ordering to be used for an existing index, you must
delete the database for the secondary index. The next time the index is
opened (via EntityStore.getSecondaryIndex
) the index will be
regenerated in the correct order. To delete the index database, first
determine the database name; see the Database Names section of the
EntityStore
javadoc. Then, before opening the
EntityStore
, delete the index database using
Environment.removeDatabase
. [#17252]
com.sleepycat.util.RuntimeExceptionWrapper: java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2554) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1297) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351) at com.sleepycat.bind.serial.SerialBinding.entryToObject(SerialBinding.java:141) at com.sleepycat.collections.DataView.makeValue(DataView.java:597) at com.sleepycat.collections.DataCursor.getCurrentValue(DataCursor.java:350) at com.sleepycat.collections.StoredContainer.getValue(StoredContainer.java:304) at com.sleepycat.collections.StoredMap.get(StoredMap.java:240)Now null values can be stored and read, as long as the value binding supports null values. Note that null values are not supported when entity bindings are used, such as when using the DPL. Thanks to 'annie' on OTN for reporting the problem. [#18633]
com.sleepycat.je.EnvironmentFailureException: java.lang.InstantiationException UNEXPECTED_EXCEPTION: Unexpected internal Exception, may have side effects. at com.sleepycat.je.EnvironmentFailureException.unexpectedException(EnvironmentFailureException.java:286) at com.sleepycat.compat.DbCompat.unexpectedException(DbCompat.java:494) at com.sleepycat.persist.impl.ReflectionAccessor.newInstance(ReflectionAccessor.java:157) at com.sleepycat.persist.impl.ComplexFormat.checkNewSecKeyInitializer(ComplexFormat.java:475) at com.sleepycat.persist.impl.ComplexFormat.initialize(ComplexFormat.java:451) at com.sleepycat.persist.impl.Format.initializeIfNeeded(Format.java:542) at com.sleepycat.persist.impl.PersistCatalog.init(PersistCatalog.java:454) at com.sleepycat.persist.impl.PersistCatalog.Now adding new secondary keys into abstract entity classes is allowed in the DPL. Thanks to user 786189 on OTN for reporting the problem. [#19358](PersistCatalog.java:221) at com.sleepycat.persist.impl.Store. (Store.java:186) at com.sleepycat.persist.EntityStore. (EntityStore.java:185)
IllegalStateException
is now thrown when calling
EntityStore.setSequenceConfig
and the sequence has already been
opened via a call to EntityStore.getPrimaryIndex
. This is the
behavior previously specified in the javadoc for
setSequenceConfig
. Thanks to patriciaG on OTN for
reporting
the problem. [#19356]
java.lang.IllegalArgumentException: Class could not be loaded or is not persistent.Now storing an enum class with constant-specific methods is allowed in the DPL. Thanks to Mikhail Barg on OTN for reporting the problem. [#18357]
Allows to register enum or array types by EntityModel.registerClass. This new feature will be useful when enum or array classes are unknown for DPL but will be used in converter mutation.
Also collects the related formats for the Map or Collection types in the FieldInfo.collectRelatedFormats, e.g., creates an EnumFormat for MyEnum class when meeting Map<String, MyEnum>.
Thanks to James on OTN for reporting the problem. [#19377]In our benchmark, there are 500,000 records containing only String fields, and the size of each record is 180 bytes. With such changes, the reading performance gains 14% improvement, and the writing performance gains 10% improvement. [#19247]
In our benchmark, there are 500,000 records. The primary key in each record is a composite key containing an integer field and a String field, and the size of each record is 180 bytes. With such change, the performance of PrimaryIndex.get operation (reads 500,000 records, uses pre-load mode to avoid I/O process) gains nearly 10% improvement.
The improvement will be more significant if there is a large and complex primary key and small data. [#19248]EnvironmentFailureException
is now thrown by
Environment.close() if the last open Environment
handle
is closed between calls to DbBackup.startBackup()
and DbBackup.endBackup()
. [19207]
EnvironmentConfig.setCacheSize
.