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.dbc;
22 
23 import berkeleydb.c;
24 import berkeleydb.dbexception;
25 import berkeleydb.db;
26 import berkeleydb.dbt;
27 import berkeleydb.dbenv;
28 import berkeleydb.dbstream;
29 import std.stdint;
30 import std.string;
31 
32 class Dbc
33 {
34 private:
35 	DBC *dbc = null;
36     DbEnv dbenv;
37     int opened;
38     bool join; // join cursor may use only get&close methods
39 
40 package:
41     @property DBC *_DBC() {return dbc;}
42     @property int _opened() {return opened;}
43     @property bool _join() {return join;}
44 
45 	this(DBC *dbc, bool join, DbEnv dbenv)
46 	{
47         this.dbc = dbc;
48         this.join = join;
49         this.dbenv = dbenv;
50         opened = 1;
51 	}
52 
53 public:
54 	~this()
55 	{
56 		if (opened > 0) close();
57 	}
58 
59 	void close()
60 	{
61         if (opened < 0) {
62 			throw new DbWrongUsingException("Closing closed Dbc");
63 		}
64 		auto ret = dbc.close(dbc);
65         opened = -1;
66 		DbRetCodeToException(ret, dbenv);
67         assert(ret == 0);
68 	}
69 
70     int cmp(Dbc other_cursor, uint32_t flags = 0)
71     {
72         if (opened < 0) {
73             throw new DbWrongUsingException("Operation on closed Dbc");
74         }
75         if (join) {
76             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
77         }
78         if (other_cursor._opened < 0) {
79             throw new DbWrongUsingException("Operation on closed Dbc (other_cursor argument)");
80         }
81         if (other_cursor._join) {
82             throw new DbWrongUsingException("Only get&close operations permitted for join cursor (other_cursor argument)");
83         }
84         int res;
85         auto ret = dbc.cmp(dbc, other_cursor._DBC, &res, flags);
86         DbRetCodeToException(ret, dbenv);
87         assert(ret == 0);
88         return res;
89     }
90 
91     db_recno_t count(uint32_t flags = 0)
92     {
93         if (opened < 0) {
94             throw new DbWrongUsingException("Operation on closed Dbc");
95         }
96         if (join) {
97             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
98         }
99         uint32_t res;
100         auto ret = dbc.count(dbc, &res, flags);
101         DbRetCodeToException(ret, dbenv);
102         assert(ret == 0);
103         return res;
104     }
105 
106     int del(uint32_t flags = 0)
107     {
108         if (opened < 0) {
109             throw new DbWrongUsingException("Operation on closed Dbc");
110         }
111         if (join) {
112             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
113         }
114         auto ret = dbc.del(dbc, flags);
115         return DbRetCodeToException!"Dbc.del"(ret, dbenv);
116     }
117 
118     Dbc dup(uint32_t flags = 0)
119     {
120         if (opened < 0) {
121             throw new DbWrongUsingException("Operation on closed Dbc");
122         }
123         if (join) {
124             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
125         }
126         DBC *res;
127         auto ret = dbc.dup(dbc, &res, flags);
128         DbRetCodeToException(ret, dbenv);
129         assert(ret == 0);
130         return new Dbc(res, false, dbenv);
131     }
132 
133     int get(Dbt *key, Dbt *data, uint32_t flags = 0)
134     {
135         if (opened < 0) {
136             throw new DbWrongUsingException("Operation on closed Dbc");
137         }
138         auto ret = dbc.get(dbc, &key.dbt, &data.dbt, flags);
139         DbRetCodeToException!"Dbc.get"(ret, dbenv, key);
140         DbRetCodeToException!"Dbc.get"(ret, dbenv, data);
141         return DbRetCodeToException!"Dbc.get"(ret, dbenv);
142     }
143 
144     int pget(Dbt *key, Dbt *pkey, Dbt *data, uint32_t flags = 0)
145     {
146         if (opened < 0) {
147             throw new DbWrongUsingException("Operation on closed Dbc");
148         }
149         auto ret = dbc.pget(dbc, &key.dbt, &pkey.dbt, &data.dbt, flags);
150         DbRetCodeToException!"Dbc.get"(ret, dbenv, key);
151         DbRetCodeToException!"Dbc.get"(ret, dbenv, data);
152         return DbRetCodeToException!"Dbc.get"(ret, dbenv);
153     }
154 
155     int put(Dbt *key, Dbt *data, uint32_t flags = 0)
156     {
157         if (opened < 0) {
158             throw new DbWrongUsingException("Operation on closed Dbc");
159         }
160         if (join) {
161             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
162         }
163         auto ret = dbc.put(dbc, &key.dbt, &data.dbt, flags);
164         return DbRetCodeToException!"Dbc.put"(ret, dbenv);
165     }
166 
167     void set_priority(DbCachePriority priority)
168     {
169         if (opened < 0) {
170             throw new DbWrongUsingException("Operation on closed Dbc");
171         }
172         if (join) {
173             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
174         }
175         auto ret = dbc.set_priority(dbc, priority);
176         DbRetCodeToException(ret, dbenv);
177         assert(ret == 0);
178     }
179 
180     DbCachePriority get_priority()
181     {
182         if (opened < 0) {
183             throw new DbWrongUsingException("Get configuration on closed Dbc");
184         }
185         if (join) {
186             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
187         }
188         DbCachePriority res;
189         auto ret = dbc.get_priority(dbc, &res);
190         DbRetCodeToException(ret, dbenv);
191         assert(ret == 0);
192         return res;
193     }
194 
195     /* BLOBs and Related Methods */
196 version(VERSION_6)
197 {
198     DbStream db_stream(uint32_t flags = 0)
199     {
200         if (opened < 0) {
201             throw new DbWrongUsingException("Get DbStream on closed Dbc");
202         }
203         if (join) {
204             throw new DbWrongUsingException("Only get&close operations permitted for join cursor");
205         }
206         DB_STREAM *res;
207         auto ret = dbc.db_stream(dbc, &res, flags);
208         DbRetCodeToException(ret, dbenv);
209         assert(ret == 0);
210         return new DbStream(res, dbenv);
211     }
212 }
213 }