blob: 81ae5adeddd4b8f4ac957b77f3f9883721dac174 [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 Pesavento948c50c2020-12-26 21:30:45 -05003 * Copyright (c) 2014-2020, 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
Davide Pesavento948c50c2020-12-26 21:30:45 -050023#include "common.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
Shock Jiang3016c982014-11-11 11:35:17 -080044/**
45 * @brief Database Manager, provides CRUD operations on stored entities
46 *
47 * @note Method names follow MongoDB convention: insert/remove/find/update
48 */
Davide Pesavento948c50c2020-12-26 21:30:45 -050049class DbMgr : boost::noncopyable
Shock Jiang3016c982014-11-11 11:35:17 -080050{
51public:
Shock Jiang3016c982014-11-11 11:35:17 -080052 /**
53 * @brief The Database Status
54 */
55 enum DbStatus {
56 DB_CONNECTED,
57 DB_CLOSED,
58 DB_ERROR
59 };
60
61 DEFINE_ERROR(Error, std::runtime_error);
62 DEFINE_ERROR(PrepareError, Error);
63 DEFINE_ERROR(ExecuteError, Error);
64 DEFINE_ERROR(ConnectError, Error);
65
66public:
67 explicit
Davide Pesaventod01c1a42019-01-21 21:42:45 -050068 DbMgr(const std::string& dbFile = "");
Shock Jiang3016c982014-11-11 11:35:17 -080069
70 ~DbMgr();
71
72 /**
73 * @brief connect to the database. If it's already opened, do nothing.
74 */
75 void
76 open();
77
78 /**
79 * @brief close the database connection. Do nothing if it's already closed.
80 * Destructor would automatically close the database connection as well.
81 */
82 void
83 close();
84
85 /**
86 * @brief clear all the data in the database
87 */
88 void
89 clearAllData();
90
91public: // Zone manipulation
92 DEFINE_ERROR(ZoneError, Error);
93
94 /**
95 * @brief insert the m_zone to the database, and set the zone's id.
96 * If the zone is already in the db, handle the exception without leaving it to upper level,
97 * meanwhile, set the zone's id too.
98 * @pre m_zone.getId() == 0
99 * @post m_zone.getId() > 0
100 */
101 void
102 insert(Zone& zone);
103
104 /**
Yumin Xia2c509c22017-02-09 14:37:36 -0800105 * @brief set zoneInfo by key-value
106 */
107 void
108 setZoneInfo(Zone& zone,
109 const std::string& key,
110 const Block& value);
111
112 /**
113 * @brief get zoneInfo
114 */
115 std::map<std::string, Block>
116 getZoneInfo(Zone& zone);
117
118 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800119 * @brief lookup the zone by name, fill the m_id and m_ttl
120 * @post whatever the previous id is
121 * @return true if the record exist
122 */
123 bool
124 find(Zone& zone);
125
126 /**
Jiewen Tan870b29b2014-11-17 19:09:49 -0800127 * @brief get all zones in the database
128 */
129 std::vector<Zone>
130 listZones();
131
132 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800133 * @brief remove the zone
134 * @pre m_zone.getId() > 0
135 * @post m_zone.getId() == 0
136 */
137 void
138 remove(Zone& zone);
139
140public: // Rrset manipulation
141 DEFINE_ERROR(RrsetError, Error);
142
143 /**
144 * @brief add the rrset
145 * @pre m_rrset.getId() == 0
146 * @post m_rrset.getId() > 0
147 */
148 void
149 insert(Rrset& rrset);
150
151 /**
152 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
153 *
154 * If record exists, `m_ttl`, `m_version` and `m_data` is set
155 *
156 * @pre m_rrset.getZone().getId() > 0
157 * @post whatever the previous id is,
158 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
159 * @return true if the record exist
160 */
161 bool
162 find(Rrset& rrset);
163
164 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700165 * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
166 *
167 * The lower bound rrset is the largest label that is less than rrset's label
168 * If record exists, `m_ttl`, `m_version` and `m_data` is set
169 *
170 * @pre m_rrset.getZone().getId() > 0
171 * @post whatever the previous id is,
172 * m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
173 * @return true if the record exist
174 */
175 bool
176 findLowerBound(Rrset& rrset);
177
178 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800179 * @brief get all the rrsets which is stored at given zone
180 * @throw RrsetError() if zone does not exist in the database
181 * @note if zone.getId() == 0, the function setId for the zone automatically
182 * @note all returned rrsets' m_zone point to the memory of the param[in] zone
183 */
184 std::vector<Rrset>
185 findRrsets(Zone& zone);
186
187 /**
188 * @brief remove the rrset
189 * @pre m_rrset.getId() > 0
190 * @post m_rrset.getId() == 0
191 */
192 void
193 remove(Rrset& rrset);
194
195 /**
Yumin Xia55a7cc42017-05-14 18:43:34 -0700196 * @brief remove all records of a specific type in a zone
197 */
198 void
199 removeRrsetsOfZoneByType(Zone& zone,
200 const name::Component& type);
201
202 /**
Shock Jiang3016c982014-11-11 11:35:17 -0800203 * @brief replace ttl, version, and Data with new values
204 * @pre m_rrset.getId() > 0
205 */
206 void
207 update(Rrset& rrset);
208
Shock Jiang3016c982014-11-11 11:35:17 -0800209public:
210 const std::string&
211 getDbFile() const
212 {
213 return m_dbFile;
214 }
215
216private:
Yumin Xia55a7cc42017-05-14 18:43:34 -0700217 /**
218 * @brief Save @p name to the database in the internal sortable format
219 *
220 * If @p name is not preserved until @p stmt is executed, @p isStatic must be
221 * set to `false`.
222 */
223 void
224 saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic = true);
225
226 Name
227 restoreName(sqlite3_stmt* stmt, int iCol);
228
229private:
Shock Jiang3016c982014-11-11 11:35:17 -0800230 std::string m_dbFile;
231 sqlite3* m_conn;
232};
233
234} // namespace ndns
235} // namespace ndn
236
237#endif // NDNS_DAEMON_DB_MGR_HPP