1 module fdb.database;
2 
3 import
4     std.conv,
5     std.exception,
6     std..string,
7     std.traits;
8 
9 import
10     fdb.cluster,
11     fdb.context,
12     fdb.disposable,
13     fdb.error,
14     fdb.fdb_c,
15     fdb.fdb_c_options,
16     fdb.future,
17     fdb.range,
18     fdb.rangeinfo,
19     fdb.transaction;
20 
21 shared class Database : IDatabaseContext, IDisposable
22 {
23     private const Cluster  cluster;
24     private DatabaseHandle dbh;
25 
26     private Transaction[]  transactions;
27 
28     invariant()
29     {
30         assert(cluster !is null);
31     }
32 
33     this(DatabaseHandle dbh, const shared Cluster cluster)
34     in
35     {
36         enforce(cluster !is null, "cluster must be set");
37         enforce(dbh !is null, "dbh must be set");
38     }
39     body
40     {
41         this.dbh     = cast(shared)dbh;
42         this.cluster = cluster;
43     }
44 
45     ~this()
46     {
47         dispose;
48     }
49 
50     void dispose()
51     {
52         if (!dbh) return;
53 
54         fdb_database_destroy(cast(DatabaseHandle)dbh);
55         dbh = null;
56     }
57 
58     private auto createTransactionImpl()
59     {
60         TransactionHandle th;
61         auto err = fdb_database_create_transaction(
62             cast(DatabaseHandle)dbh,
63             &th);
64         enforceError(err);
65 
66         auto tr = new shared Transaction(th, this);
67         return tr;
68     }
69 
70     auto createTransaction()
71     out (result)
72     {
73         assert(result !is null);
74     }
75     body
76     {
77         auto tr = createTransactionImpl();
78         synchronized (this)
79             transactions ~= tr;
80         return tr;
81     }
82 
83     /**
84      * Set the size of the client location cache. Raising this value can boost
85      * performance in very large databases where clients access data in a near-
86      * random pattern. Defaults to 100000.
87      * Parameter: (Int) Max location cache entries
88      */
89     void setLocationCacheSize(in long value) const
90     {
91         setDatabaseOption(DatabaseOption.LOCATION_CACHE_SIZE, value);
92     }
93 
94     /**
95      * Set the maximum number of watches allowed to be outstanding on a database
96      * connection. Increasing this number could result in increased resource
97      * usage. Reducing this number will not cancel any outstanding watches.
98      * Defaults to 10000 and cannot be larger than 1000000.
99      * Parameter: (Int) Max outstanding watches
100      */
101     void setMaxWatches(in long value) const
102     {
103         setDatabaseOption(DatabaseOption.MAX_WATCHES, value);
104     }
105 
106     /**
107      * Specify the machine ID that was passed to fdbserver processes running on
108      * the same machine as this client, for better location-aware load
109      * balancing.
110      * Parameter: (String) Hexadecimal ID
111      */
112     void setMachineId(in string value) const
113     {
114         setDatabaseOption(DatabaseOption.MACHINE_ID, value);
115     }
116 
117     /**
118      * Specify the datacenter ID that was passed to fdbserver processes running
119      * in the same datacenter as this client, for better location-aware load
120      * balancing.
121      * Parameter: (String) Hexadecimal ID
122      */
123     void setDatacenterId(in string value) const
124     {
125         setDatabaseOption(DatabaseOption.DATACENTER_ID, value);
126     }
127 
128     private void setDatabaseOption(in DatabaseOption op, in long value) const
129     {
130         const auto err = fdb_database_set_option(
131             cast(DatabaseHandle)dbh,
132             op,
133             cast(immutable(char)*)&value,
134             cast(int)value.sizeof);
135         enforceError(err);
136     }
137 
138     private void setDatabaseOption(in DatabaseOption op, in string value) const
139     {
140         const auto err = fdb_database_set_option(
141             cast(DatabaseHandle)dbh,
142             op,
143             value.toStringz,
144             cast(int)value.length);
145         enforceError(err);
146     }
147 
148     shared(Value) opIndex(in Key key)
149     {
150         scope auto tr = createTransactionImpl();
151         auto value    = tr[key];
152         tr.commit;
153         return value;
154     }
155 
156     RecordRange opIndex(RangeInfo info)
157     {
158         auto tr    = createTransaction();
159         auto value = cast(RecordRange)tr[info];
160         tr.commit;
161         return value;
162     }
163 
164     inout(Value) opIndexAssign(inout(Value) value, in Key key)
165     {
166         scope auto tr = createTransactionImpl();
167         tr[key]       = value;
168         tr.commit;
169         return value;
170     }
171 
172     void clear(in Key key)
173     {
174         scope auto tr = createTransactionImpl();
175         tr.clear(key);
176         tr.commit;
177     }
178 
179     void clearRange(in RangeInfo info)
180     {
181         scope auto tr = createTransactionImpl();
182         tr.clearRange(info);
183         tr.commit;
184     }
185 
186     void run(in WorkFunc func)
187     {
188         scope auto tr = createTransactionImpl();
189         tr.run(func);
190     }
191 
192     auto runAsync(in WorkFunc func, in VoidFutureCallback commitCallback)
193     {
194         auto tr = createTransaction();
195         return tr.runAsync(func, commitCallback);
196     }
197 }