1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #ident "$Id$"
3 /*======
4 This file is part of PerconaFT.
5 
6 
7 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
8 
9     PerconaFT is free software: you can redistribute it and/or modify
10     it under the terms of the GNU General Public License, version 2,
11     as published by the Free Software Foundation.
12 
13     PerconaFT is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
20 
21 ----------------------------------------
22 
23     PerconaFT is free software: you can redistribute it and/or modify
24     it under the terms of the GNU Affero General Public License, version 3,
25     as published by the Free Software Foundation.
26 
27     PerconaFT is distributed in the hope that it will be useful,
28     but WITHOUT ANY WARRANTY; without even the implied warranty of
29     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30     GNU Affero General Public License for more details.
31 
32     You should have received a copy of the GNU Affero General Public License
33     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
34 ======= */
35 
36 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
37 
38 #include <db.h>
39 
40 #include "cursor.hpp"
41 #include "db.hpp"
42 #include "db_env.hpp"
43 #include "db_txn.hpp"
44 #include "exceptions.hpp"
45 
46 namespace ftcxx {
47 
DBC(const DB & db,const DBTxn & txn,int flags)48     DBC::DBC(const DB &db, const DBTxn &txn, int flags)
49         : _txn(),
50           _dbc(nullptr)
51     {
52         if (db.db() != nullptr) {
53             DB_TXN *txnp = txn.txn();
54             if (txnp == nullptr) {
55                 _txn = DBTxn(DBEnv(db.db()->dbenv), DB_TXN_READ_ONLY | DB_READ_UNCOMMITTED);
56                 txnp = _txn.txn();
57             }
58 
59             ::DBC *c;
60             int r = db.db()->cursor(db.db(), txnp, &c, flags);
61             handle_ft_retval(r);
62             _dbc = c;
63         }
64     }
65 
DBC(const DBEnv & env,const DBTxn & txn)66     DBC::DBC(const DBEnv &env, const DBTxn &txn)
67         : _txn(),
68           _dbc(nullptr)
69     {
70         if (env.env() != nullptr) {
71             DB_TXN *txnp = txn.txn();
72             if (txnp == nullptr) {
73                 _txn = DBTxn(env, DB_TXN_READ_ONLY | DB_READ_UNCOMMITTED);
74                 txnp = _txn.txn();
75             }
76 
77             ::DBC *c;
78             int r = env.env()->get_cursor_for_directory(env.env(), txnp, &c);
79             handle_ft_retval(r);
80             _dbc = c;
81         }
82     }
83 
~DBC()84     DBC::~DBC() {
85         if (_dbc != nullptr) {
86             close();
87         }
88     }
89 
close()90     void DBC::close() {
91         int r = _dbc->c_close(_dbc);
92         handle_ft_retval(r);
93         _dbc = nullptr;
94     }
95 
set_range(const IterationStrategy & strategy,const Bounds & bounds,YDB_CALLBACK_FUNCTION callback,void * extra) const96     bool DBC::set_range(const IterationStrategy &strategy, const Bounds &bounds, YDB_CALLBACK_FUNCTION callback, void *extra) const {
97         int r = dbc()->c_set_bounds(dbc(), bounds.left_dbt(), bounds.right_dbt(), strategy.prelock, 0);
98         handle_ft_retval(r);
99 
100         if (strategy.forward) {
101             if (bounds.left_infinite()) {
102                 r = dbc()->c_getf_first(dbc(), strategy.getf_flags(), callback, extra);
103             } else {
104                 r = dbc()->c_getf_set_range(dbc(), strategy.getf_flags(), const_cast<DBT *>(bounds.left_dbt()), callback, extra);
105             }
106         } else {
107             if (bounds.right_infinite()) {
108                 r = dbc()->c_getf_last(dbc(), strategy.getf_flags(), callback, extra);
109             } else {
110                 r = dbc()->c_getf_set_range_reverse(dbc(), strategy.getf_flags(), const_cast<DBT *>(bounds.right_dbt()), callback, extra);
111             }
112         }
113         if (r == DB_NOTFOUND) {
114             return false;
115         } else if (r != 0 && r != -1) {
116             handle_ft_retval(r);
117         }
118         return true;
119     }
120 
advance(const IterationStrategy & strategy,YDB_CALLBACK_FUNCTION callback,void * extra) const121     bool DBC::advance(const IterationStrategy &strategy, YDB_CALLBACK_FUNCTION callback, void *extra) const {
122         int r;
123         if (strategy.forward) {
124             r = dbc()->c_getf_next(dbc(), strategy.getf_flags(), callback, extra);
125         } else {
126             r = dbc()->c_getf_prev(dbc(), strategy.getf_flags(), callback, extra);
127         }
128         if (r == DB_NOTFOUND) {
129             return false;
130         } else if (r != 0 && r != -1) {
131             handle_ft_retval(r);
132         }
133         return true;
134     }
135 
136 } // namespace ftcxx
137