summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/cql_connection.h
blob: 9d81d93626e0b4aef8042e07ffb0f34201100c3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2015-2017 Deutsche Telekom AG.
//
// Authors: Razvan Becheriu <razvan.becheriu@qualitance.com>
//          Andrei Pavel <andrei.pavel@qualitance.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//           http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CQL_CONNECTION_H
#define CQL_CONNECTION_H

#include <dhcpsrv/database_connection.h>

#include <cassandra.h>

#include <cstring>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

namespace isc {
namespace dhcp {

/// @brief Pair containing major and minor versions
/// @todo: This is already defined in lease_mgr.h. Need to have one
/// definition. May need to move it if necessary.
typedef std::pair<uint32_t, uint32_t> VersionPair;

/// @brief Statement index representing the statement name
typedef char const* const StatementTag;

/// @brief Define CQL backend version. The CASS_VERSION_* constants
///        are defined in a header provided by cpp-driver.
/// @{
constexpr uint32_t CQL_DRIVER_VERSION_MAJOR = CASS_VERSION_MAJOR;
constexpr uint32_t CQL_DRIVER_VERSION_MINOR = CASS_VERSION_MINOR;
/// @}

/// Define CQL schema version: 3.0
/// @{
constexpr uint32_t CQL_SCHEMA_VERSION_MAJOR = 3u;
constexpr uint32_t CQL_SCHEMA_VERSION_MINOR = 0u;
/// @}

/// @brief Defines a single statement or query
struct CqlTaggedStatement {

    /// Short description of the query
    StatementTag name_;

    /// Text representation of the actual query
    char const* const text_;

    /// Internal Cassandra object representing the prepared statement
    const CassPrepared* prepared_statement_;

    /// Should the statement be executed raw or with binds?
    bool is_raw_;

    /// @brief Constructor
    /// @param name brief name of the query
    /// @param text text (CQL) representation of the query
    CqlTaggedStatement(StatementTag name, char const* const text)
        : name_(name), text_(text), prepared_statement_(NULL), is_raw_(false) {
    }

    /// @brief Constructor
    /// @param name brief name of the query
    /// @param text text (CQL) representation of the query
    /// @param is_raw should the statement be executed raw?
    CqlTaggedStatement(StatementTag name, char const* const text, bool const& is_raw)
        : name_(name), text_(text), prepared_statement_(NULL), is_raw_(is_raw) {
    }
};

/// @brief Hash function for StatementMap keys
///
/// Delegates to std::hash<std::string>.
struct StatementTagHash {
    size_t operator()(StatementTag const& key) const {
        return std::hash<std::string>{}(std::string(key));
    }
};

/// @brief Equality function for StatementMap keys
struct StatementTagEqual {
    bool operator()(StatementTag const& lhs, StatementTag const& rhs) const {
        return std::strcmp(lhs, rhs) == 0;
    }
};

/// @brief A container for all statements.
typedef std::unordered_map<StatementTag, CqlTaggedStatement,
                           StatementTagHash, StatementTagEqual> StatementMap;

/// @brief A type for a single entry on the statements map
typedef std::pair<StatementTag, CqlTaggedStatement> StatementMapEntry;

/// @brief Common CQL connector pool
///
/// Provides common operations for the Cassandra database connection used by
/// CqlLeaseMgr, CqlHostDataSource and CqlSrvConfigMgr. Manages the connection
/// to the Cassandra database and preparing of compiled statements. Its fields
/// are public because they are used (both set and retrieved) in classes that
/// use instances of CqlConnection.
class CqlConnection : public DatabaseConnection {
public:
    /// @brief Constructor
    ///
    /// Initialize CqlConnection object with parameters needed for connection.
    /// @param parameters specify the connection details (username, ip addresses etc.)
    explicit CqlConnection(const ParameterMap& parameters);

    /// @brief Destructor
    virtual ~CqlConnection();

    /// @brief Prepare statements
    ///
    /// Creates the prepared statements for all of the CQL statements used
    /// by the CQL backend.
    /// @param statements statements to be prepared
    ///
    /// @throw isc::dhcp::DbOperationError if an operation on the open database
    ///     has failed
    /// @throw isc::InvalidParameter if there is an invalid access in the
    ///     vector. This represents an internal error within the code.
    void prepareStatements(StatementMap& statements);

    /// @brief Open database
    ///
    /// Opens the database using the information supplied in the parameters
    /// passed to the constructor. If no parameters are supplied, the default
    /// values will be used. The parameters supported as as follows (default
    /// values specified in parentheses):
    /// - keyspace: name of the database to which to connect (keatest)
    /// - contact-points: IP addresses of the nodes to connect to (127.0.0.1)
    /// - port: The TCP port to use (9042)
    /// - user - credentials to use when connecting (no username)
    /// - password - credentails to use when connecting (no password)
    /// - reconnect-wait-time 2000
    /// - connect-timeout 5000
    /// - request-timeout 12000
    /// - tcp-keepalive no
    /// - tcp-nodelay no
    ///
    /// @throw DbOpenError error opening the database
    void openDatabase();

    /// @brief Set consistency
    void setConsistency(bool force, CassConsistency consistency);

    /// @brief Start transaction
    void startTransaction();

    /// @brief Commit Transactions
    virtual void commit();

    /// @brief Rollback Transactions
    virtual void rollback();

    /// @brief Check for errors
    ///
    /// Check for errors on the current database operation and returns text
    /// description of what happened. In case of success, also returns
    /// some logging friendly text.
    ///
    /// @param what text description of the operation
    /// @param future the structure that holds the status of operation
    /// @param statement_tag statement that was used (optional)
    /// @return text description of the error
    static const std::string
    checkFutureError(const std::string& what,
                     CassFuture* future,
                     StatementTag statement_tag = NULL);

    /// @brief Pointer to external array of tagged statements containing
    ///     statement name, array of names of bind parameters and text query
    StatementMap statements_;

    /// @brief CQL connection handle
    CassCluster* cluster_;

    /// @brief CQL session handle
    CassSession* session_;

    /// @brief CQL consistency
    CassConsistency consistency_;

    // @brief Schema meta information, used for UDTs
    const CassSchemaMeta* schema_meta_;

    /// @brief Keyspace meta information, used for UDTs
    const CassKeyspaceMeta* keyspace_meta_;

    /// @brief CQL consistency enabled
    bool force_consistency_;
};

typedef std::shared_ptr<CqlConnection> CqlConnectionPtr;

}  // namespace dhcp
}  // namespace isc

#endif  // CQL_CONNECTION_H