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 buffer = cast(ubyte[])Mallocator.instance.allocate(4096*64); 27 version(Lmdb) mdb_load_libs(); 28 db.open(filename); 29 } 30 void close() { 31 db.close(); 32 Mallocator.instance.deallocate(buffer); 33 } 34 35 ubyte[] tempBuffer() @property { return buffer; } 36 37 //----------------------------------------------- 38 version(Lmdb) { 39 private enum Table : ulong 40 { 41 world, 42 dimention, 43 region, 44 chunk, 45 } 46 void putPerWorldValue(K)(K key, ubyte[] value) { 47 put(formKey(key), Table.world, value); 48 } 49 ubyte[] getPerWorldValue(K)(K key) { 50 return get(formKey(key), Table.world); 51 } 52 void putPerChunkValue(ulong key, ubyte[] value) { 53 put(key, Table.chunk, value); 54 } 55 ubyte[] getPerChunkValue(ulong key) { 56 return get(key, Table.chunk); 57 } 58 59 private void put(ulong key, ulong table, ubyte[] value) { 60 ubyte[16] dbKey; 61 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 62 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 63 db.put(dbKey, value); 64 } 65 private ubyte[] get(ulong key, ulong table) { 66 ubyte[16] dbKey; 67 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 68 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 69 return db.get(dbKey); 70 } 71 private void del(ulong key, ulong table) { 72 ubyte[16] dbKey; 73 (*cast(ulong[2]*)dbKey.ptr)[0] = key; 74 (*cast(ulong[2]*)dbKey.ptr)[1] = table; 75 return db.del(dbKey); 76 } 77 } 78 79 version(Sqlite) { 80 void putPerWorldValue(K)(K key, ubyte[] value) { 81 db.savePerWorldData(key, value); 82 } 83 ubyte[] getPerWorldValue(K)(K key) { 84 return db.loadPerWorldData(key); 85 } 86 void putPerChunkValue(ulong key, ubyte[] value) { 87 db.savePerChunkData(key, value); 88 } 89 ubyte[] getPerChunkValue(ulong key) { 90 return db.loadPerChunkData(key); 91 } 92 } 93 94 //----------------------------------------------- 95 void beginTxn() { 96 db.beginTxn(); 97 } 98 void abortTxn() { 99 db.abortTxn(); 100 } 101 void commitTxn() { 102 db.commitTxn(); 103 } 104 } 105 106 ulong formKey(K)(K _key) @nogc 107 if (is(K == string) || is(K == ulong)) 108 { 109 static if (is(K == string)) 110 return hashBytes(cast(ubyte[])_key); 111 else static if (is(K == ulong)) 112 return _key; 113 } 114 115 ulong hashBytes(ubyte[] bytes) @nogc 116 { 117 ulong hash = 5381; 118 119 foreach(c; bytes) 120 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 121 122 return hash; 123 }