| RDB 2

transactions.hpp
Go to the documentation of this file.
1 /*
2 *******************************************************************************
3 *
4 * Copyright 2025 RIEGL Laser Measurement Systems
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * SPDX-License-Identifier: Apache-2.0
19 *
20 *******************************************************************************
21 */
22 /*!
23 *******************************************************************************
24 *
25 * \file transactions.hpp
26 * \author RIEGL LMS GmbH, Austria
27 * \brief Manage point cloud transactions
28 * \version 2015-10-14/AW: Initial version
29 * \version 2017-11-24/AW: Constructors declared as "explicit" (#2825)
30 * \version 2021-11-17/AW: New function to discard transaction data (#3843)
31 * \version 2021-11-18/AW: New function to estimate transaction size (#3837)
32 *
33 *******************************************************************************
34 */
35
36 #ifndef RIEGL_RDB_POINTCLOUD_TRANSACTIONS_HPP
37 #define RIEGL_RDB_POINTCLOUD_TRANSACTIONS_HPP
38
39 //---< INCLUDES >---------------------------------------------------------------
40
41 #include <memory>
42 #include <string>
43 #include <vector>
44 #include <cstdlib>
45 #include <utility>
46
47 #include "riegl/rdb/pointcloud/pointcloudData.hpp"
48 #include "riegl/rdb/pointcloud/transaction.hpp"
49 #include "riegl/rdb/progress.hpp"
50
51 //---< NAMESPACE >--------------------------------------------------------------
52
53 namespace riegl {
54 namespace rdb {
55 namespace pointcloud {
56
57 //---< CLASS Transactions >-----------------------------------------------------
58 /*!
59 * \brief Manage point cloud transactions
60 *
61 * Modifying the point cloud database means to execute a transaction.
62 *
63 * This class allows to start new transactions (see begin()) and to
64 * browse past (already executed) transactions.
65 *
66 * \see riegl::rdb::Pointcloud::transaction()
67 */
68 class Transactions
69 {
70 public:
71 /*!
72 * \brief Constructor
73 * \note You cannot create new Transactions objects directly,
74 * use riegl::rdb::Pointcloud::transaction() instead.
75 */
76 explicit Transactions(riegl::rdb::PointcloudData* pointcloud);
77
78 /*!
79 * \brief Create new transaction
80 *
81 * Whenever you are going to modify the point cloud, you must create a
82 * transaction by using this function. Without a transaction, any function
83 * that modifies the point cloud will fail (i.e. it throws an exception).
84 *
85 * A transaction automatically locks the database so that other users
86 * can query data but can __NOT__ add or modify data. Please note that
87 * only __one transaction at a time__ is allowed. If there is already
88 * a transaction pending, this function will raise an exception (see
89 * Error::TransactionPending).
90 *
91 * To finish a transaction either call commit() or rollback().
92 *
93 * \note Parameters 'title' and 'agent' are required - i.e. creating
94 * a new transaction will fail if empty strings are provided.
95 * All other parameters are optional.
96 *
97 * \note Parameters 'comments' and 'settings' serve the user and client
98 * application for information, e.g. to repeat processing steps
99 * later on. They have no influence on the transaction itself. The
100 * client application is free to store information in any format
101 * that is string-compatible (e.g. plain text, INI, XML, JSON).
102 *
103 * \note The total size of the 'title', 'agent', 'comments' and 'settings'
104 * strings must not exceed 500 MB (bytes, not characters).
105 */
106 Transaction::ID begin(
107 const std::string &title, //!< [in] short description, e.g. "Import"
108 const std::string &agent, //!< [in] software name, e.g. "rdbimport v1.0"
109 const std::string &comments = "", //!< [in] e.g. process details for humans
110 const std::string &settings = "" //!< [in] e.g. process settings for software
111 );
112
113 /*!
114 * \brief Commit current transaction
115 *
116 * This function commits the current transaction. All changes made by the
117 * transaction become visible to others.
118 */
119 void commit(
120 Progress progress = nullptr, //!< [in] commit progress callback function
121 void *userdata = nullptr, //!< [in] progress callback function user data
122 const std::uint32_t signature = 0, //!< [in] signature method (0: none, 1: default)
123 const std::uint32_t key_size = 0, //!< [in] signature encryption key size (at least 32 byte)
124 const void* const key_data = nullptr //!< [in] signature encryption key buffer
125 );
126
127 /*!
128 * \brief Commit current transaction
129 *
130 * Overloaded commit() that takes any callable type as progress callback.
131 */
132 template<typename Callable>
133 void commit(
134 Callable &&progress, //!< [in] progress callback function
135 const std::uint32_t signature = 0, //!< [in] signature method (0: none, 1: default)
136 const std::uint32_t key_size = 0, //!< [in] signature encryption key size (at least 32 byte)
137 const void* const key_data = nullptr //!< [in] signature encryption key buffer
138 )
139 {
140 typedef typename std::decay<Callable>::type CallableType;
141 this->commit(
142 &progress_proxy_callable<CallableType>,
143 const_cast<CallableType*>(&progress),
144 signature, key_size, key_data
145 );
146 }
147
148 /*!
149 * \brief Commit current transaction
150 *
151 * Overloaded commit() that takes a progress callback method of an object.
152 */
153 template<typename Receiver>
154 void commit(
155 void (Receiver::*progress)(std::uint8_t), Receiver &receiver,
156 const std::uint32_t signature = 0, //!< [in] signature method (0: none, 1: default)
157 const std::uint32_t key_size = 0, //!< [in] signature encryption key size (at least 32 byte)
158 const void* const key_data = nullptr //!< [in] signature encryption key buffer
159 )
160 {
161 auto userdata = std::make_pair(progress, &receiver);
162 this->commit(
163 &progress_proxy_receiver<Receiver>, &userdata,
164 signature, key_size, key_data
165 );
166 }
167
168 /*!
169 * \brief Commit current transaction
170 *
171 * Overloaded commit() that takes a constant progress callback method
172 * of a constant object.
173 */
174 template<typename Receiver>
175 void commit(
176 void (Receiver::*progress)(std::uint8_t) const, const Receiver &receiver,
177 const std::uint32_t signature = 0, //!< [in] signature method (0: none, 1: default)
178 const std::uint32_t key_size = 0, //!< [in] signature encryption key size (at least 32 byte)
179 const void* const key_data = nullptr //!< [in] signature encryption key buffer
180 )
181 {
182 auto userdata = std::make_pair(progress, &receiver);
183 this->commit(
184 &progress_proxy_receiver<Receiver>, &userdata,
185 signature, key_size, key_data
186 );
187 }
188
189 /*!
190 * \brief Abort current transaction
191 *
192 * This function rolls back the current transaction and causes all changes
193 * made by the transaction to be discarded.
194 */
195 void rollback();
196
197 /*!
198 * \brief Get list of transactions
199 *
200 * The database keeps a log (journal) of all transactions. This function
201 * returns a list of identifiers (IDs) for all recorded transactions.
202 */
203 std::vector<Transaction::ID> list() const;
204
205 /*!
206 * \brief ID of current transaction
207 *
208 * This function returns the ID of the current transaction. Usually this
209 * is the transaction that was committed at last. However, if restore() is
210 * used to return to a previous database state, the current transaction is
211 * the restored transaction.
212 *
213 * \note This function does not return the ID of a pending transaction.
214 */
215 Transaction::ID current() const;
216
217 /*!
218 * \brief Check if transaction is pending
219 *
220 * This function checks whether there is a pending transaction that was
221 * started by __this__ database instance. This function does __not__ check
222 * whether a transaction was started by a different database instance of
223 * the current or different thread or process.
224 */
225 bool pending() const;
226
227 /*!
228 * \brief Query transaction details
229 */
230 Transaction details(
231 const Transaction::ID transaction //!< [in] transaction identifier
232 ) const;
233
234 /*!
235 * \brief Restore database state
236 *
237 * This function restores the database state that was current at the end
238 * of the transaction. Those transactions that were created after the
239 * restored transaction remain valid until a new transaction is created.
240 * This offers some simple undo/redo functionality.
241 */
242 void restore(
243 const Transaction::ID transaction //!< [in] transaction identifier
244 );
245
246 /*!
247 * \brief Discard transaction data
248 *
249 * This function deletes the given transaction(s). Please note that this
250 * operation only removes the transaction(s) from the database history and
251 * releases the related data blocks in the database file so that they can
252 * be re-used by subsequent transactions. However the database file size
253 * will not decrease unless you call vacuum().
254 *
255 * \note The first (database creation) and the current transaction
256 * (last committed or restored) can not be deleted.
257 *
258 * \see riegl::rdb::pointcloud::Management::finalize()
259 * \see riegl::rdb::pointcloud::Management::vacuum()
260 */
261 void discard(
262 const Transaction::ID transaction //!< [in] transaction identifier
263 );
264
265 //! \copydoc discard()
266 void discard(
267 const std::vector<Transaction::ID> &transactions //!< [in] transaction identifiers
268 );
269
270 /*!
271 * \brief Estimate database size
272 *
273 * This function returns the size (in bytes) of all data of the specified
274 * transactions, which is approximately the file size of a database that
275 * contains only these transactions (and no gaps).
276 *
277 * \note Data blocks may be shared among multiple transactions and size()
278 * returns the total size of the union of all used data blocks. That
279 * is why size(1) + size(2) is not necessarily equal to size(1, 2).
280 *
281 * \see riegl::rdb::pointcloud::Transactions::discard()
282 * \see riegl::rdb::pointcloud::Management::finalize()
283 * \see riegl::rdb::pointcloud::Management::vacuum()
284 */
285 std::uint64_t size(
286 const Transaction::ID transaction //!< [in] transaction identifier
287 ) const;
288
289 //! \copydoc size()
290 std::uint64_t size(
291 const std::vector<Transaction::ID> &transactions //!< [in] transaction identifiers
292 ) const;
293
294 private:
295 riegl::rdb::PointcloudData *data;
296
297 template<typename Callable>
298 static void progress_proxy_callable(std::uint8_t progress, void *userdata)
299 {
300 try
301 {
302 Callable &callback = *reinterpret_cast<Callable*>(userdata);
303 callback(progress); // = invoke original callback
304 }
305 catch(...)
306 {
307 // ignore all errors
308 }
309 }
310
311 template<typename Receiver>
312 static void progress_proxy_receiver(std::uint8_t progress, void *userdata)
313 {
314 try
315 {
316 typedef void (Receiver::*Function)(std::uint8_t); // just a shortcut...
317 auto data(reinterpret_cast<std::pair<Function, Receiver*>*>(userdata));
318 (*data->second.*data->first)(progress); // = invoke original callback
319 }
320 catch(...)
321 {
322 // ignore all errors
323 }
324 }
325 };
326
327 }}} // namespace riegl::rdb::pointcloud
328
329 #endif // RIEGL_RDB_POINTCLOUD_TRANSACTIONS_HPP
riegl::rdb::pointcloud::Transactions
Manage point cloud transactions.
Definition: transactions.hpp:68
progress.hpp
Operation progress feedback tools.
riegl::rdb::pointcloud::Transactions::commit
void commit(Progress progress=nullptr, void *userdata=nullptr, const std::uint32_t signature=0, const std::uint32_t key_size=0, const void *const key_data=nullptr)
Commit current transaction.
riegl::rdb::pointcloud::Transactions::commit
void commit(Callable &&progress, const std::uint32_t signature=0, const std::uint32_t key_size=0, const void *const key_data=nullptr)
Commit current transaction.
Definition: transactions.hpp:133
riegl::rdb::pointcloud::Transactions::restore
void restore(const Transaction::ID transaction)
Restore database state.
transaction.hpp
Point cloud transaction.
riegl::rdb::pointcloud::Transaction
Point cloud transaction.
Definition: transaction.hpp:57
riegl::rdb::pointcloud::Transactions::size
std::uint64_t size(const Transaction::ID transaction) const
Estimate database size.
riegl::rdb::Progress
void(* Progress)(std::uint8_t progress, void *userdata)
Progress callback function type.
Definition: progress.hpp:67
riegl::rdb::pointcloud::Transactions::begin
Transaction::ID begin(const std::string &title, const std::string &agent, const std::string &comments="", const std::string &settings="")
Create new transaction.
riegl
RIEGL Laser Measurement Systems GmbH, Austria.
Definition: context.hpp:48
riegl::rdb::pointcloud::Transactions::details
Transaction details(const Transaction::ID transaction) const
Query transaction details.
riegl::rdb::pointcloud::Transactions::rollback
void rollback()
Abort current transaction.
riegl::rdb::pointcloud::Transactions::Transactions
Transactions(riegl::rdb::PointcloudData *pointcloud)
Constructor.
riegl::rdb::pointcloud::Transactions::commit
void commit(void(Receiver::*progress)(std::uint8_t) const, const Receiver &receiver, const std::uint32_t signature=0, const std::uint32_t key_size=0, const void *const key_data=nullptr)
Commit current transaction.
Definition: transactions.hpp:175
riegl::rdb::pointcloud::Transactions::list
std::vector< Transaction::ID > list() const
Get list of transactions.
riegl::rdb::pointcloud::Transactions::commit
void commit(void(Receiver::*progress)(std::uint8_t), Receiver &receiver, const std::uint32_t signature=0, const std::uint32_t key_size=0, const void *const key_data=nullptr)
Commit current transaction.
Definition: transactions.hpp:154
riegl::rdb::pointcloud::Transactions::current
Transaction::ID current() const
ID of current transaction.
riegl::rdb::pointcloud::Transaction::ID
std::uint32_t ID
Definition: transaction.hpp:60
pointcloudData.hpp
Pointcloud class implementation details.
riegl::rdb::pointcloud::Transactions::pending
bool pending() const
Check if transaction is pending.
riegl::rdb::pointcloud::Transactions::discard
void discard(const Transaction::ID transaction)
Discard transaction data.