blob: 8b838387b850faa82b5c6812dc148779b7ede333 [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"
Shock Jiang3016c982014-11-11 11:35:17 -080024#include "rrset.hpp"
Junxiao Shi15e51bc2018-12-12 13:48:56 -070025#include "zone.hpp"
Shock Jiang3016c982014-11-11 11:35:17 -080026
Davide Pesaventoa3ec7552018-01-01 23:41:41 -050027#include <map>
Shock Jiang3016c982014-11-11 11:35:17 -080028#include <sqlite3.h>
29
30namespace ndn {
31namespace ndns {
32
33#define DEFINE_ERROR(ErrorName, Base) \
34class ErrorName : public Base \
35{ \
Yumin Xia2c509c22017-02-09 14:37:36 -080036public: \
Shock Jiang3016c982014-11-11 11:35:17 -080037 explicit \
38 ErrorName(const std::string& what) \
39 : Base(what) \
40 { \
41 } \
Alexander Afanasyevc7c99002015-10-09 17:27:30 -070042}
Shock Jiang3016c982014-11-11 11:35:17 -080043
44
45
46/**
47 * @brief Database Manager, provides CRUD operations on stored entities
48 *
49 * @note Method names follow MongoDB convention: insert/remove/find/update
50 */
51class DbMgr : noncopyable
52{
53public:
54
55 /**
56 * @brief The Database Status
57 */
58 enum DbStatus {
59 DB_CONNECTED,
60 DB_CLOSED,
61 DB_ERROR
62 };
63
64 DEFINE_ERROR(Error, std::runtime_error);
65 DEFINE_ERROR(PrepareError, Error);
66 DEFINE_ERROR(ExecuteError, Error);
67 DEFINE_ERROR(ConnectError, Error);
68
69public:
70 explicit
71 DbMgr(const std::string& dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db");
72
73 ~DbMgr();
74
75 /**
76 * @brief connect to the database. If it's already opened, do nothing.
77 */
78 void
79 open();
80
81 /**
82 * @brief close the database connection. Do nothing if it's already closed.
83 * Destructor would automatically close the database connection as well.
84 */
85 void
86 close();
87
88 /**
89 * @brief clear all the data in the database
90 */
91 void
92 clearAllData();
93
94public: // Zone manipulation
95 DEFINE_ERROR(ZoneError, Error);
96
97 /**
98 * @brief insert the m_zone to the database, and set the zone's id.
99 * If the zone is already in the db, handle the exception without leaving it to upper level,
100 * meanwhile, set the zone's id too.
101 * @pre m_zone.getId() == 0
102 * @post m_zone.getId() > 0
103 */
104 void
105 insert(Zone& zone);
106
107 /**
Yumin Xia2c509c22017-02-09 14:37:36 -0800108 * @brief set zoneInfo by key-value
109 */
110 void
111 setZoneInfo(Zone& zone,
112 const std::string& key,
113 const Block& value);
114
115 /**
116 * @brief get zoneInfo
117 */
118 std::map<std::string, Block>
119 getZoneInfo(Zone& zone);
120
121 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800122 * @brief lookup the zone by name, fill the m_id and m_ttl
123 * @post whatever the previous id is
124 * @return true if the record exist
125 */
126 bool
127 find(Zone& zone);
128
129 /**
Jiewen Tan870b29b2014-11-17 19:09:49 -0800130 * @brief get all zones in the database
131 */
132 std::vector<Zone>
133 listZones();
134
135 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800136 * @brief remove the zone
137 * @pre m_zone.getId() > 0
138 * @post m_zone.getId() == 0
139 */
140 void
141 remove(Zone& zone);
142
143public: // Rrset manipulation
144 DEFINE_ERROR(RrsetError, Error);
145
146 /**
147 * @brief add the rrset
148 * @pre m_rrset.getId() == 0
149 * @post m_rrset.getId() > 0
150 */
151 void
152 insert(Rrset& rrset);
153
154 /**
155 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
156 *
157 * If record exists, `m_ttl`, `m_version` and `m_data` is set
158 *
159 * @pre m_rrset.getZone().getId() > 0
160 * @post whatever the previous id is,
161 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
162 * @return true if the record exist
163 */
164 bool
165 find(Rrset& rrset);
166
167 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700168 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
169 *
170 * The lower bound rrset is the largest label that is less than rrset's label
171 * If record exists, `m_ttl`, `m_version` and `m_data` is set
172 *
173 * @pre m_rrset.getZone().getId() > 0
174 * @post whatever the previous id is,
175 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
176 * @return true if the record exist
177 */
178 bool
179 findLowerBound(Rrset& rrset);
180
181 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800182 * @brief get all the rrsets which is stored at given zone
183 * @throw RrsetError() if zone does not exist in the database
184 * @note if zone.getId() == 0, the function setId for the zone automatically
185 * @note all returned rrsets' m_zone point to the memory of the param[in] zone
186 */
187 std::vector<Rrset>
188 findRrsets(Zone& zone);
189
190 /**
191 * @brief remove the rrset
192 * @pre m_rrset.getId() > 0
193 * @post m_rrset.getId() == 0
194 */
195 void
196 remove(Rrset& rrset);
197
198 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700199 * @brief remove all records of a specific type in a zone
200 */
201 void
202 removeRrsetsOfZoneByType(Zone& zone,
203 const name::Component& type);
204
205 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800206 * @brief replace ttl, version, and Data with new values
207 * @pre m_rrset.getId() > 0
208 */
209 void
210 update(Rrset& rrset);
211
212 ////////////////////////////////
213 ////////getter and setter
214public:
215 const std::string&
216 getDbFile() const
217 {
218 return m_dbFile;
219 }
220
221private:
Yumin Xia55a7cc42017-05-14 18:43:34 -0700222 /**
223 * @brief Save @p name to the database in the internal sortable format
224 *
225 * If @p name is not preserved until @p stmt is executed, @p isStatic must be
226 * set to `false`.
227 */
228 void
229 saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic = true);
230
231 Name
232 restoreName(sqlite3_stmt* stmt, int iCol);
233
234private:
Shock Jiang3016c982014-11-11 11:35:17 -0800235 std::string m_dbFile;
236 sqlite3* m_conn;
237};
238
239} // namespace ndns
240} // namespace ndn
241
242#endif // NDNS_DAEMON_DB_MGR_HPP