RDB 2
transactions.hpp
Go to the documentation of this file.
1 /*
2  *******************************************************************************
3  *
4  * Copyright 2023 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 
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  */
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  */
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  */
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
progress.hpp
Operation progress feedback tools.
riegl::rdb::pointcloud::Transactions::Transactions
Transactions(riegl::rdb::PointcloudData *pointcloud)
Constructor.
riegl::rdb::pointcloud::Transactions::discard
void discard(const Transaction::ID transaction)
Discard transaction data.
riegl
RIEGL Laser Measurement Systems GmbH, Austria.
Definition: context.hpp:48
riegl::rdb::pointcloud::Transactions::current
Transaction::ID current() const
ID of current transaction.
riegl::rdb::pointcloud::Transaction
Point cloud transaction.
Definition: transaction.hpp:57
riegl::rdb::pointcloud::Transaction::ID
std::uint32_t ID
Definition: transaction.hpp:60
riegl::rdb::pointcloud::Transactions::size
std::uint64_t size(const Transaction::ID transaction) const
Estimate database size.
riegl::rdb::pointcloud::Transactions::pending
bool pending() const
Check if transaction is pending.
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::restore
void restore(const Transaction::ID transaction)
Restore database state.
riegl::rdb::pointcloud::Transactions
Manage point cloud transactions.
Definition: transactions.hpp:68
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.
transaction.hpp
Point cloud transaction.
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::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.
pointcloudData.hpp
Pointcloud class implementation details.
riegl::rdb::Progress
void(* Progress)(std::uint8_t progress, void *userdata)
Progress callback function type.
Definition: progress.hpp:67
riegl::rdb::pointcloud::Transactions::rollback
void rollback()
Abort 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::details
Transaction details(const Transaction::ID transaction) const
Query transaction details.