1 /*
2    bdb2d is BerkeleyDB for D language
3    It is part of unDE project (http://unde.su)
4 
5    Copyright (C) 2009-2014 Nikolay (unDEFER) Krivchenkov <undefer@gmail.com>
6 
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 module berkeleydb.dbsequence;
22 
23 import berkeleydb.c;
24 import berkeleydb.dbt;
25 import berkeleydb.db;
26 import berkeleydb.dbtxn;
27 import berkeleydb.dbexception;
28 import berkeleydb.dbenv;
29 
30 import std.stdint;
31 import std.string;
32 import std.conv;
33 
34 alias DB_SEQUENCE_STAT DbSequenceStat;
35 
36 class DbSequence
37 {
38 private:
39 	DB_SEQUENCE *dbsequence = null;
40     Db db;
41     DbEnv dbenv;
42     int opened = 0;
43 
44 package:
45     @property DB_SEQUENCE *_DB_SEQUENCE() {return dbsequence;}
46     @property int _opened() {return opened;}
47 
48 public:
49 	this(Db db, uint32_t flags = 0)
50 	{
51         this.db = db;
52         dbenv = db._dbenv;
53 		auto ret = db_sequence_create(&dbsequence, db?db._DB:null, flags);
54 		DbRetCodeToException(ret, dbenv);
55         assert(ret == 0);
56 	}
57 
58 	~this()
59 	{
60 		if (opened >= 0) close();
61 	}
62 
63     void open(DbTxn txnid, Dbt *key, uint32_t flags = 0)
64     {
65 		if (opened > 0) {
66 			throw new DbWrongUsingException("Opening opened DbSequence");
67 		}
68 		if (opened < 0) {
69 			throw new DbWrongUsingException("Opening closed/removed DbSequence");
70 		}
71 		auto ret = dbsequence.open(dbsequence, txnid?txnid._DB_TXN:null, &key.dbt, flags);
72 		DbRetCodeToException(ret, dbenv);
73         assert(ret == 0);
74         opened++;
75     }
76 
77 	void close(uint32_t flags = 0)
78 	{
79 		if (opened < 0) {
80 			throw new DbWrongUsingException("Closing closed/removed DbSequence");
81 		}
82 		auto ret = dbsequence.close(dbsequence, flags);
83         opened = -1;
84 		DbRetCodeToException(ret, dbenv);
85         assert(ret == 0);
86 	}
87 
88     db_seq_t get(DbTxn txnid, uint32_t delta, uint32_t flags = 0)
89     {
90 		if (opened < 0) {
91 			throw new DbWrongUsingException("Operation on closed/removed DbSequence");
92 		}
93         db_seq_t res;
94         auto ret = dbsequence.get(dbsequence, txnid?txnid._DB_TXN:null, delta, &res, flags);
95         DbRetCodeToException(ret, dbenv);
96         assert(ret == 0);
97         return res;
98     }
99 
100     Db get_dbp()
101     {
102         return db;
103     }
104 
105     void get_key(Dbt *key)
106     {
107 		if (opened < 0) {
108 			throw new DbWrongUsingException("Operation on closed/removed DbSequence");
109 		}
110         auto ret = dbsequence.get_key(dbsequence, &key.dbt);
111         DbRetCodeToException(ret, dbenv);
112         assert(ret == 0);
113     }
114 
115     void initial_value(db_seq_t value)
116     {
117 		if (opened < 0) {
118 			throw new DbWrongUsingException("Configuration of closed/removed DbSequence");
119 		}
120 		if (opened > 0) {
121 			throw new DbWrongUsingException("Configuration of opened DbSequence");
122 		}
123         auto ret = dbsequence.initial_value(dbsequence, value);
124         DbRetCodeToException(ret, dbenv);
125         assert(ret == 0);
126     }
127 
128     void remove(DbTxn txnid, uint32_t flags = 0)
129     {
130 		if (opened < 0) {
131 			throw new DbWrongUsingException("Removing closed/removed DbSequence");
132 		}
133 		auto ret = dbsequence.remove(dbsequence, txnid?txnid._DB_TXN:null, flags);
134         opened = -1;
135 		DbRetCodeToException(ret, dbenv);
136         assert(ret == 0);
137     }
138 
139     DbSequenceStat *stat(uint32_t flags = 0)
140     {
141 		if (opened < 0) {
142 			throw new DbWrongUsingException("Operation on closed/removed DbSequence");
143 		}
144         DbSequenceStat *res;
145 		auto ret = dbsequence.stat(dbsequence, &res, flags);
146 		DbRetCodeToException(ret, dbenv);
147         assert(ret == 0);
148         return res;
149     }
150 
151     void stat_print(uint32_t flags = 0)
152     {
153 		if (opened < 0) {
154 			throw new DbWrongUsingException("Operation on closed/removed DbSequence");
155 		}
156 		auto ret = dbsequence.stat_print(dbsequence, flags);
157 		DbRetCodeToException(ret, dbenv);
158         assert(ret == 0);
159     }
160 
161     /* Sequences Configuration */
162     void set_cachesize(uint32_t size)
163     {
164 		if (opened < 0) {
165 			throw new DbWrongUsingException("Configuration of closed/removed DbSequence");
166 		}
167 		if (opened > 0) {
168 			throw new DbWrongUsingException("Configuration of opened DbSequence");
169 		}
170 		auto ret = dbsequence.set_cachesize(dbsequence, size);
171 		DbRetCodeToException(ret, dbenv);
172         assert(ret == 0);
173     }
174 
175 version(VERSION_6)
176 {
177     uint32_t get_cachesize()
178     {
179         if (opened < 0) {
180             throw new DbWrongUsingException("Configuration on closed DbSequence");
181         }
182         uint32_t res;
183         auto ret = dbsequence.get_cachesize(dbsequence, &res);
184         DbRetCodeToException(ret, dbenv);
185         assert(ret == 0);
186         return res;
187     }
188 }
189 
190     void set_flags(uint32_t flags = 0)
191     {
192 		if (opened < 0) {
193 			throw new DbWrongUsingException("Configuration of closed/removed DbSequence");
194 		}
195 		if (opened > 0) {
196 			throw new DbWrongUsingException("Configuration of opened DbSequence");
197 		}
198 		auto ret = dbsequence.set_flags(dbsequence, flags);
199 		DbRetCodeToException(ret, dbenv);
200         assert(ret == 0);
201     }
202 
203     uint32_t get_flags()
204     {
205         if (opened < 0) {
206             throw new DbWrongUsingException("Configuration on closed DbSequence");
207         }
208         uint32_t res;
209         auto ret = dbsequence.get_flags(dbsequence, &res);
210         DbRetCodeToException(ret, dbenv);
211         assert(ret == 0);
212         return res;
213     }
214 
215     void set_range(db_seq_t min, db_seq_t max)
216     {
217 		if (opened < 0) {
218 			throw new DbWrongUsingException("Configuration of closed/removed DbSequence");
219 		}
220 		if (opened > 0) {
221 			throw new DbWrongUsingException("Configuration of opened DbSequence");
222 		}
223 		auto ret = dbsequence.set_range(dbsequence, min, max);
224 		DbRetCodeToException(ret, dbenv);
225         assert(ret == 0);
226     }
227 
228     void get_range(ref db_seq_t min, ref db_seq_t max)
229     {
230 		if (opened < 0) {
231 			throw new DbWrongUsingException("Configuration of closed/removed DbSequence");
232 		}
233 		auto ret = dbsequence.get_range(dbsequence, &min, &max);
234 		DbRetCodeToException(ret, dbenv);
235         assert(ret == 0);
236     }
237 }