Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  Copyright (c) 2012 Jan Kotek
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
 
 package org.mapdb;
 
 
 import java.io.File;
 import java.util.Set;

A builder class for creating and opening a database.

Author(s):
Jan Kotek
 
 public class DBMaker<DBMakerT extends DBMaker<DBMakerT>> {
 
     protected static final byte CACHE_DISABLE = 0;
     protected static final byte CACHE_FIXED_HASH_TABLE = 1;
     protected static final byte CACHE_HARD_REF = 2;
     protected static final byte CACHE_WEAK_REF = 3;
     protected static final byte CACHE_SOFT_REF = 4;
     protected static final byte CACHE_LRU = 5;
 
     protected byte _cache = ;
     protected int _cacheSize = 1024*32;

    
file to open, if null opens in memory store
 
     protected File _file;
 
     protected boolean _transactionEnabled = true;
 
     protected boolean _asyncWriteEnabled = true;
     protected int _asyncFlushDelay = .;
 
     protected boolean _deleteFilesAfterClose = false;
     protected boolean _readOnly = false;
     protected boolean _closeOnJvmShutdown = false;
 
     protected boolean _compressionEnabled = false;
 
     protected byte[] _xteaEncryptionKey = null;
 
     protected int _freeSpaceReclaimQ = 5;
 
     protected boolean _checksumEnabled = false;
 
     protected boolean _ifInMemoryUseDirectBuffer = false;
 
     protected boolean _syncOnCommitDisabled = false;
 
     protected boolean _snapshotEnabled = false;
 
     protected long _sizeLimit = 0;
 
     protected int _rafMode = 0;
 
     protected boolean _strictDBGet = false;
 
     protected boolean _appendStorage;
 
     protected boolean _fullTx = false;

    
use static factory methods, or make subclass
 
     protected DBMaker(){}
 
     protected DBMaker(File file) {
         this. = file;
     }

    
Creates new in-memory database. Changes are lost after JVM exits.

This will use HEAP memory so Garbage Collector is affected.

 
     public static DBMaker newMemoryDB(){
         return new DBMaker(null);
     }
 
     public DBMakerT _newMemoryDB(){
         this. = null;
         return getThis();
     }


    
Creates new in-memory database. Changes are lost after JVM exits.

This will use DirectByteBuffer outside of HEAP, so Garbage Collector is not affected

    public static DBMaker newDirectMemoryDB(){
        return new DBMaker()._newDirectMemoryDB();
    }
    public  DBMakerT _newDirectMemoryDB() {
         = null;
         = true;
        return getThis();
    }


    
Creates or open append-only database stored in file. This database uses format otherthan usual file db

Parameters:
file
Returns:
maker
    public static DBMaker newAppendFileDB(File file) {
        return new DBMaker()._newAppendFileDB(file);
    }
    public DBMakerT _newAppendFileDB(File file) {
         = file;
         = true;
        return getThis();
    }


    
Create new BTreeMap backed by temporary file storage. This is quick way to create 'throw away' collection.

Storage is created in temp folder and deleted on JVM shutdown

    public static <K,V> BTreeMap<K,V> newTempTreeMap(){
        return newTempFileDB()
                .deleteFilesAfterClose()
                .closeOnJvmShutdown()
                .transactionDisable()
                .make()
                .getTreeMap("temp");
    }

    
Create new HTreeMap backed by temporary file storage. This is quick way to create 'throw away' collection.

Storage is created in temp folder and deleted on JVM shutdown

    public static <K,V> HTreeMap<K,V> newTempHashMap(){
        return newTempFileDB()
                .deleteFilesAfterClose()
                .closeOnJvmShutdown()
                .transactionDisable()
                .make()
                .getHashMap("temp");
    }

    
Create new TreeSet backed by temporary file storage. This is quick way to create 'throw away' collection.

Storage is created in temp folder and deleted on JVM shutdown

    public static <K> NavigableSet<K> newTempTreeSet(){
        return newTempFileDB()
                .deleteFilesAfterClose()
                .closeOnJvmShutdown()
                .transactionDisable()
                .make()
                .getTreeSet("temp");
    }

    
Create new HashSet backed by temporary file storage. This is quick way to create 'throw away' collection.

Storage is created in temp folder and deleted on JVM shutdown

    public static <K> Set<K> newTempHashSet(){
        return newTempFileDB()
                .deleteFilesAfterClose()
                .closeOnJvmShutdown()
                .transactionDisable()
                .make()
                .getHashSet("temp");
    }

    
Creates new database in temporary folder.

Returns:
    public static DBMaker newTempFileDB() {
        try {
            return newFileDB(File.createTempFile("mapdb-temp","db"));
        } catch (IOException e) {
            throw new IOError(e);
        }
    }


    
Creates or open database stored in file.
    public static DBMaker newFileDB(File file){
        return new DBMaker(file);
    }
    public DBMakerT _newFileDB(File file){
        this. = file;
        return getThis();
    }
    protected DBMakerT getThis(){
        return (DBMakerT)this;
    }

    
Transaction journal is enabled by default You must call DB.commit() to save your changes. It is possible to disable transaction journal for better write performance In this case all integrity checks are sacrificed for faster speed.

If transaction journal is disabled, all changes are written DIRECTLY into store. You must call DB.close() method before exit, otherwise your store WILL BE CORRUPTED

Returns:
this builder
    public DBMakerT transactionDisable(){
        this. = false;
        return getThis();
    }


    
Instance cache is enabled by default. This greatly decreases serialization overhead and improves performance. Call this method to disable instance cache, so an object will always be deserialized.

This may workaround some problems

Returns:
this builder
    public DBMakerT cacheDisable(){
        this. = ;
        return getThis();
    }

    
Enables unbounded hard reference cache. This cache is good if you have lot of available memory.

All fetched records are added to HashMap and stored with hard reference. To prevent OutOfMemoryExceptions MapDB monitors free memory, if it is bellow 25% cache is cleared.

Returns:
this builder
    public DBMakerT cacheHardRefEnable(){
        this. = ;
        return getThis();
    }


    
Enables unbounded cache which uses WeakReference. Items are removed from cache by Garbage Collector

Returns:
this builder
    public DBMakerT cacheWeakRefEnable(){
        this. = ;
        return getThis();
    }

    
Enables unbounded cache which uses SoftReference. Items are removed from cache by Garbage Collector

Returns:
this builder
    public DBMakerT cacheSoftRefEnable(){
        this. = ;
        return getThis();
    }

    
Enables Least Recently Used cache. It is fixed size cache and it removes less used items to make space.

Returns:
this builder
    public DBMakerT cacheLRUEnable(){
        this. = ;
        return getThis();
    }
    
Enables compatibility storage mode for 32bit JVMs.

By default MapDB uses memory mapped files. However 32bit JVM can only address 4GB of memory. Also some older JVMs do not handle large memory mapped files well. We can use FileChannel which does not use memory mapped files, but is slower. Use this if you are experiencing java.lang.OutOfMemoryError: Map failed exceptions

This options disables memory mapped files but causes storage to be slower.

    public DBMakerT randomAccessFileEnable() {
         = 2;
        return getThis();
    }


    
Same as randomAccessFileEnable(), but part of storage is kept memory mapped. This mode is good performance compromise between memory mapped files and RAF.

Index file is typically 5% of storage. It contains small frequently read values, which is where memory mapped file excel.

With this mode you will experience java.lang.OutOfMemoryError: Map failed exceptions eventually. But storage size limit is pushed to somewhere around 40GB.

    public DBMakerT randomAccessFileEnableKeepIndexMapped() {
        this. = 1;
        return getThis();
    }

    
Check current JVM for known problems. If JVM does not handle large memory files well, this option disables memory mapped files, and use safer and slower RandomAccessFile instead.
    public DBMakerT randomAccessFileEnableIfNeeded() {
        this. = Utils.JVMSupportsLargeMappedFiles()? 0:2;
        return getThis();
    }

    
Set cache size. Interpretations depends on cache type. For fixed size caches (such as FixedHashTable cache) it is maximal number of items in cache.

For unbounded caches (such as HardRef cache) it is initial capacity of underlying table (HashMap).

Default cache size is 32768.

Parameters:
cacheSize new cache size
Returns:
this builder
    public DBMakerT cacheSize(int cacheSize){
        this. = cacheSize;
        return getThis();
    }

    
MapDB supports snapshots. `TxEngine` requires additional locking which has small overhead when not used. Snapshots are disabled by default. This option switches the snapshots on.

Returns:
this builder
    public DBMakerT snapshotEnable(){
        this. = true;
        return getThis();
    }


    
By default all modifications are queued and written into disk on Background Writer Thread. So all modifications are performed in asynchronous mode and do not block.

It is possible to disable Background Writer Thread, but this greatly hurts concurrency. Without async writes, all threads blocks until all previous writes are not finished (single big lock).

This may workaround some problems

Returns:
this builder
    public DBMakerT asyncWriteDisable(){
        this. = false;
        return getThis();
    }



    
Set flush iterval for write cache, by default is 0

When BTreeMap is constructed from ordered set, tree node size is increasing linearly with each item added. Each time new key is added to tree node, its size changes and storage needs to find new place. So constructing BTreeMap from ordered set leads to large store fragmentation.

Setting flush interval is workaround as BTreeMap node is always updated in memory (write cache) and only final version of node is stored on disk.

Parameters:
delay flush write cache every N miliseconds
Returns:
this builder
    public DBMakerT asyncFlushDelay(int delay){
         = delay;
        return getThis();
    }


    
Try to delete files after DB is closed. File deletion may silently fail, especially on Windows where buffer needs to be unmapped file delete.

Returns:
this builder
    public DBMakerT deleteFilesAfterClose(){
        this. = true;
        return getThis();
    }

    
Adds JVM shutdown hook and closes DB just before JVM;

Returns:
this builder
    public DBMakerT closeOnJvmShutdown(){
        this. = true;
        return getThis();
    }

    
Enables record compression.

Make sure you enable this every time you reopen store, otherwise record de-serialization fails unpredictably.

Returns:
this builder
    public DBMakerT compressionEnable(){
        this. = true;
        return getThis();
    }


    
Encrypt storage using XTEA algorithm.

XTEA is sound encryption algorithm. However implementation in MapDB was not peer-reviewed. MapDB only encrypts records data, so attacker may see number of records and their sizes.

Make sure you enable this every time you reopen store, otherwise record de-serialization fails unpredictably.

Parameters:
password for encryption
Returns:
this builder
    public DBMakerT encryptionEnable(String password){
        return encryptionEnable(password.getBytes(.));
    }



    
Encrypt storage using XTEA algorithm.

XTEA is sound encryption algorithm. However implementation in MapDB was not peer-reviewed. MapDB only encrypts records data, so attacker may see number of records and their sizes.

Make sure you enable this every time you reopen store, otherwise record de-serialization fails unpredictably.

Parameters:
password for encryption
Returns:
this builder
    public DBMakerT encryptionEnable(byte[] password){
         = password;
        return getThis();
    }


    
Adds Adler32 checksum at end of each record to check data integrity. It throws 'IOException("Checksum does not match, data broken")' on de-serialization if data are corrupted

Make sure you enable this every time you reopen store, otherwise record de-serialization fails.

Returns:
this builder
    public DBMakerT checksumEnable(){
        this. = true;
        return getThis();
    }


    
DB Get methods such as DB.getTreeMap(java.lang.String) or DB.getAtomicLong(java.lang.String) auto create new record with default values, if record with given name does not exist. This could be problem if you would like to enforce stricter database schema. So this parameter disables record auto creation. If this set, `DB.getXX()` will throw an exception if given name does not exist, instead of creating new record (or collection)

Returns:
this builder
    public DBMakerT strictDBGet(){
        this. = true;
        return getThis();
    }




    
Open store in read-only mode. Any modification attempt will throw UnsupportedOperationException("Read-only")

Returns:
this builder
    public DBMakerT readOnly(){
        this. = true;
        return getThis();
    }



    
Set free space reclaim Q. It is value from 0 to 10, indicating how eagerly MapDB searchs for free space inside store to reuse, before expanding store file. 0 means that no free space will be reused and store file will just grow (effectively append only). 10 means that MapDB tries really hard to reuse free space, even if it may hurt performance. Default value is 5;

Returns:
this builder
    public DBMakerT freeSpaceReclaimQ(int q){
        if(q<0||q>10) throw new IllegalArgumentException("wrong Q");
        this. = q;
        return getThis();
    }

    
Enables power saving mode. Typically MapDB runs daemon threads in infinitive cycle with delays and spin locks:
     while(true){
         Thread.sleep(1000);
         doSomething();
     }

    while(write_finished){
         write_chunk;
         sleep(10 nanoseconds)  //so OS gets chance to finish async writing
     }

 
This brings bit more stability (prevents deadlocks) and some extra speed. However it causes higher CPU usage then necessary, also CPU wakes-up every N seconds.

On power constrained devices (phones, laptops..) trading speed for energy consumption is not desired. So this settings tells MapDB to prefer energy efficiency over speed and stability. This is global settings, so this settings may affects any MapDB part where this settings makes sense

Currently is used only in AsyncWriteEngine where power settings may prevent Background Writer Thread from exiting, if main thread dies.

Returns:
this builder
//    public DBMaker powerSavingModeEnable(){
//        this._powerSavingMode = true;
//        return this;
//    }

    
Disables file sync on commit. This way transactions are preserved (rollback works), but commits are not 'durable' and data may be lost if store is not properly closed. File store will get properly synced when closed. Disabling this will make commits faster.

Returns:
this builder
    public DBMakerT syncOnCommitDisable(){
        this. = true;
        return getThis();
    }


    
Sets store size limit. Disk or memory space consumed be storage should not grow over this space. Limit is not strict and does not apply to some parts such as index table. Actual store size might be 10% or more bigger.

Parameters:
maxSize maximal store size in GB
Returns:
this builder
    public DBMakerT sizeLimit(double maxSize){
        this. = (long) (maxSize * 1024D*1024D*1024D);
        return getThis();
    }




    
constructs DB using current settings
    public DB make(){
        return new DB(makeEngine(), );
    }
    
    public TxMaker makeTxMaker(){
        this.true;
        snapshotEnable();
        asyncWriteDisable();
        Engine e = makeEngine();
        if(!(e instanceof TxEngine)) throw new IllegalArgumentException("Snapshot must be enabled for TxMaker");
        //init catalog if needed
        DB db = new DB(e);
        db.commit();
        return new TxMaker((TxEnginee);
    }

    
constructs Engine using current settings
    public Engine makeEngine(){
        if( && ==null)
            throw new UnsupportedOperationException("Can not open in-memory DB in read-only mode.");
        if( && !.exists() && !){
            throw new UnsupportedOperationException("Can not open non-existing file in read-only mode.");
        }
        if(>0 && )
            throw new UnsupportedOperationException("Append-Only store does not support Size Limit");
        extendArgumentCheck();
        Engine engine;
        if(!){
            Volume.Factory folFac = extendStoreVolumeFactory();
            engine =  ?
                    extendStoreWAL(folFac) :
                    extendStoreDirect(folFac);
        }else{
            if(==nullthrow new UnsupportedOperationException("Append Storage format is not supported with in-memory dbs");
            engine = extendStoreAppend();
        }
        engine = extendWrapStore(engine);
        if( && !){
            engine = extendAsyncWriteEngine(engine);
        }
        if( == ){
            //do not wrap engine in cache
        }else if( == ){
            engine = extendCacheHashTable(engine);
        }else if ( == ){
            engine = extendCacheHardRef(engine);
        }else if ( == ){
            engine = extendCacheWeakRef(engine);
        }else if ( == ){
            engine = extendCacheSoftRef(engine);
        }else if ( == ){
            engine = extendCacheLRU(engine);
        }
        engine = extendWrapCache(engine);
        if()
            engine = extendSnapshotEngine(engine);
        engine = extendWrapSnapshotEngine(engine);
        if()
            engine = new ReadOnlyEngine(engine);
        if(){
            final Engine engine2 = engine;
            Runtime.getRuntime().addShutdownHook(new Thread("MapDB shutdown") {
                @Override
				public void run() {
                    if(!engine2.isClosed())
                        extendShutdownHookBefore(engine2);
                        engine2.close();
                        extendShutdownHookAfter(engine2);
                }
            });
        }
        //try to read one record from DB, to make sure encryption and compression are correctly set.
        Fun.Tuple2<Integer,Stringcheck = null;
        try{
            check = (Fun.Tuple2<IntegerString>) engine.get(..);
            if(check!=null){
                if(check.a.intValue()!= check.b.hashCode())
                    throw new RuntimeException("invalid checksum");
            }
        }catch(Throwable e){
            throw new IllegalArgumentException("Error while opening store. Make sure you have right password, compression or encryption is well configured.",e);
        }
        if(check == null && !engine.isReadOnly()){
            //new db, so insert testing record
            String s = Utils.randomString(127); //random string so it is not that easy to decrypt
            check = Fun.t2(s.hashCode(), s);
            engine.update(.check.);
            engine.commit();
        }
        return engine;
    }
    protected void extendShutdownHookBefore(Engine engine) {
    }
    protected void extendShutdownHookAfter(Engine engine) {
    }
    protected TxEngine extendSnapshotEngine(Engine engine) {
        return new TxEngine(engine,);
    }
    protected Caches.LRU extendCacheLRU(Engine engine) {
        return new Caches.LRU(engine);
    }
    protected Caches.WeakSoftRef extendCacheWeakRef(Engine engine) {
        return new Caches.WeakSoftRef(engine,true);
    }
    protected Caches.WeakSoftRef extendCacheSoftRef(Engine engine) {
        return new Caches.WeakSoftRef(engine,false);
    }
    protected Caches.HardRef extendCacheHardRef(Engine engine) {
        return new Caches.HardRef(engine,);
    }
    protected Caches.HashTable extendCacheHashTable(Engine engine) {
        return new Caches.HashTable(engine,);
    }
    protected AsyncWriteEngine extendAsyncWriteEngine(Engine engine) {
        return new AsyncWriteEngine(enginenull);
    }
    protected void extendArgumentCheck() {
    }
    protected Engine extendWrapStore(Engine engine) {
        return engine;
    }
    protected Engine extendWrapCache(Engine engine) {
        return engine;
    }
    protected Engine extendWrapSnapshotEngine(Engine engine) {
        return engine;
    }
    protected StoreAppend extendStoreAppend() {
    }
    protected Store extendStoreDirect(Volume.Factory folFac) {
    }
    protected Store extendStoreWAL(Volume.Factory folFac) {
    }
    protected Volume.Factory extendStoreVolumeFactory() {
        return  == null?
                    Volume.memoryFactory(,):
                    Volume.fileFactory(,);
    }
New to GrepCode? Check out our FAQ X