blob: ff0066e2d5e30bba47245661d79722f501646416 [file] [log] [blame]
Shock Jiang3016c982014-11-11 11:35:17 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yumin Xia2c509c22017-02-09 14:37:36 -08002/*
Davide Pesaventoa3ec7552018-01-01 23:41:41 -05003 * Copyright (c) 2014-2018, Regents of the University of California.
Shock Jiang3016c982014-11-11 11:35:17 -08004 *
5 * This file is part of NDNS (Named Data Networking Domain Name Service).
6 * See AUTHORS.md for complete list of NDNS authors and contributors.
7 *
8 * NDNS is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NDNS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NDNS, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef NDNS_DAEMON_DB_MGR_HPP
21#define NDNS_DAEMON_DB_MGR_HPP
22
23#include "config.hpp"
24#include "zone.hpp"
25#include "rrset.hpp"
26
Davide Pesaventoa3ec7552018-01-01 23:41:41 -050027#include <map>
Shock Jiang3016c982014-11-11 11:35:17 -080028#include <ndn-cxx/common.hpp>
29#include <sqlite3.h>
30
31namespace ndn {
32namespace ndns {
33
34#define DEFINE_ERROR(ErrorName, Base) \
35class ErrorName : public Base \
36{ \
Yumin Xia2c509c22017-02-09 14:37:36 -080037public: \
Shock Jiang3016c982014-11-11 11:35:17 -080038 explicit \
39 ErrorName(const std::string& what) \
40 : Base(what) \
41 { \
42 } \
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070043}
Shock Jiang3016c982014-11-11 11:35:17 -080044
45
46
47/**
48 * @brief Database Manager, provides CRUD operations on stored entities
49 *
50 * @note Method names follow MongoDB convention: insert/remove/find/update
51 */
52class DbMgr : noncopyable
53{
54public:
55
56 /**
57 * @brief The Database Status
58 */
59 enum DbStatus {
60 DB_CONNECTED,
61 DB_CLOSED,
62 DB_ERROR
63 };
64
65 DEFINE_ERROR(Error, std::runtime_error);
66 DEFINE_ERROR(PrepareError, Error);
67 DEFINE_ERROR(ExecuteError, Error);
68 DEFINE_ERROR(ConnectError, Error);
69
70public:
71 explicit
72 DbMgr(const std::string& dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db");
73
74 ~DbMgr();
75
76 /**
77 * @brief connect to the database. If it's already opened, do nothing.
78 */
79 void
80 open();
81
82 /**
83 * @brief close the database connection. Do nothing if it's already closed.
84 * Destructor would automatically close the database connection as well.
85 */
86 void
87 close();
88
89 /**
90 * @brief clear all the data in the database
91 */
92 void
93 clearAllData();
94
95public: // Zone manipulation
96 DEFINE_ERROR(ZoneError, Error);
97
98 /**
99 * @brief insert the m_zone to the database, and set the zone's id.
100 * If the zone is already in the db, handle the exception without leaving it to upper level,
101 * meanwhile, set the zone's id too.
102 * @pre m_zone.getId() == 0
103 * @post m_zone.getId() > 0
104 */
105 void
106 insert(Zone& zone);
107
108 /**
Yumin Xia2c509c22017-02-09 14:37:36 -0800109 * @brief set zoneInfo by key-value
110 */
111 void
112 setZoneInfo(Zone& zone,
113 const std::string& key,
114 const Block& value);
115
116 /**
117 * @brief get zoneInfo
118 */
119 std::map<std::string, Block>
120 getZoneInfo(Zone& zone);
121
122 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800123 * @brief lookup the zone by name, fill the m_id and m_ttl
124 * @post whatever the previous id is
125 * @return true if the record exist
126 */
127 bool
128 find(Zone& zone);
129
130 /**
Jiewen Tan870b29b2014-11-17 19:09:49 -0800131 * @brief get all zones in the database
132 */
133 std::vector<Zone>
134 listZones();
135
136 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800137 * @brief remove the zone
138 * @pre m_zone.getId() > 0
139 * @post m_zone.getId() == 0
140 */
141 void
142 remove(Zone& zone);
143
144public: // Rrset manipulation
145 DEFINE_ERROR(RrsetError, Error);
146
147 /**
148 * @brief add the rrset
149 * @pre m_rrset.getId() == 0
150 * @post m_rrset.getId() > 0
151 */
152 void
153 insert(Rrset& rrset);
154
155 /**
156 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
157 *
158 * If record exists, `m_ttl`, `m_version` and `m_data` is set
159 *
160 * @pre m_rrset.getZone().getId() > 0
161 * @post whatever the previous id is,
162 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
163 * @return true if the record exist
164 */
165 bool
166 find(Rrset& rrset);
167
168 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700169 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
170 *
171 * The lower bound rrset is the largest label that is less than rrset's label
172 * If record exists, `m_ttl`, `m_version` and `m_data` is set
173 *
174 * @pre m_rrset.getZone().getId() > 0
175 * @post whatever the previous id is,
176 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
177 * @return true if the record exist
178 */
179 bool
180 findLowerBound(Rrset& rrset);
181
182 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800183 * @brief get all the rrsets which is stored at given zone
184 * @throw RrsetError() if zone does not exist in the database
185 * @note if zone.getId() == 0, the function setId for the zone automatically
186 * @note all returned rrsets' m_zone point to the memory of the param[in] zone
187 */
188 std::vector<Rrset>
189 findRrsets(Zone& zone);
190
191 /**
192 * @brief remove the rrset
193 * @pre m_rrset.getId() > 0
194 * @post m_rrset.getId() == 0
195 */
196 void
197 remove(Rrset& rrset);
198
199 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700200 * @brief remove all records of a specific type in a zone
201 */
202 void
203 removeRrsetsOfZoneByType(Zone& zone,
204 const name::Component& type);
205
206 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800207 * @brief replace ttl, version, and Data with new values
208 * @pre m_rrset.getId() > 0
209 */
210 void
211 update(Rrset& rrset);
212
213 ////////////////////////////////
214 ////////getter and setter
215public:
216 const std::string&
217 getDbFile() const
218 {
219 return m_dbFile;
220 }
221
222private:
Yumin Xia55a7cc42017-05-14 18:43:34 -0700223 /**
224 * @brief Save @p name to the database in the internal sortable format
225 *
226 * If @p name is not preserved until @p stmt is executed, @p isStatic must be
227 * set to `false`.
228 */
229 void
230 saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic = true);
231
232 Name
233 restoreName(sqlite3_stmt* stmt, int iCol);
234
235private:
Shock Jiang3016c982014-11-11 11:35:17 -0800236 std::string m_dbFile;
237 sqlite3* m_conn;
238};
239
240} // namespace ndns
241} // namespace ndn
242
243#endif // NDNS_DAEMON_DB_MGR_HPP