1 /** 2 Copyright: Copyright (c) 2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.world.worlddb; 7 8 import std.experimental.allocator.mallocator; 9 import voxelman.world.db.lmdbworlddb; 10 import voxelman.world.db.sqliteworlddb; 11 12 version(Windows) { 13 version = Lmdb; 14 } else { 15 version = Sqlite; 16 } 17 18 final class WorldDb 19 { 20 version(Lmdb) LmdbWorldDb db; 21 version(Sqlite) SqliteWorldDb db; 22 private ubyte[] buffer; 23 24 //----------------------------------------------- 25 void open(string filename) { 26 version(Lmdb) mdb_load_libs(); 27 db.open(filename); 28 } 29 void close() { 30 db.close(); 31 if (buffer !is null) Mallocator.instance.deallocate(buffer); 32 } 33 34 ubyte[] tempBuffer() @property { 35 if (buffer is null) buffer = cast(ubyte[])Mallocator.instance.allocate(4096*64); 36 37 return buffer; 38 } 39 40 //----------------------------------------------- 41 version(Lmdb) { 42 private enum Table : ulong 43 { 44 world, 45 dimention, 46 region, 47 chunk, 48 } 49 void putPerWorldValue(K)(K key, ubyte[] value) { 50 put(formKey(key), Table.world, value); 51 } 52 ubyte[] getPerWorldValue(K)(K key) { 53 return get(formKey(key), Table.world); 54 } 55 void putPerChunkValue(ulong key, ubyte[] value) { 56 put(key, Table.chunk, value); 57 } 58 ubyte[] getPerChunkValue(ulong key) { 59 return get(key, Table.chunk); 60 } 61 62 private void put(ulong key, ulong table, ubyte[] value) { 63 ubyte[16] dbKey; 64 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 65 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 66 db.put(dbKey, value); 67 } 68 private ubyte[] get(ulong key, ulong table) { 69 ubyte[16] dbKey; 70 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 71 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 72 return db.get(dbKey); 73 } 74 private void del(ulong key, ulong table) { 75 ubyte[16] dbKey; 76 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 77 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 78 return db.del(dbKey); 79 } 80 } 81 82 version(Sqlite) { 83 void putPerWorldValue(K)(K key, ubyte[] value) { 84 db.savePerWorldData(key, value); 85 } 86 ubyte[] getPerWorldValue(K)(K key) { 87 return db.loadPerWorldData(key); 88 } 89 void putPerChunkValue(ulong key, ubyte[] value) { 90 db.savePerChunkData(key, value); 91 } 92 ubyte[] getPerChunkValue(ulong key) { 93 return db.loadPerChunkData(key); 94 } 95 } 96 97 //----------------------------------------------- 98 void beginTxn() { 99 db.beginTxn(); 100 } 101 void abortTxn() { 102 db.abortTxn(); 103 } 104 void commitTxn() { 105 db.commitTxn(); 106 } 107 } 108 109 ulong formKey(K)(K _key) @nogc 110 if (is(K == string) || is(K == ulong)) 111 { 112 static if (is(K == string)) 113 return hashBytes(cast(ubyte[])_key); 114 else static if (is(K == ulong)) 115 return _key; 116 } 117 118 ulong hashBytes(ubyte[] bytes) @nogc 119 { 120 ulong hash = 5381; 121 122 foreach(c; bytes) 123 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 124 125 return hash; 126 }