Joedb 9.5.0
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Writable_Client.h
Go to the documentation of this file.
1#ifndef joedb_Writable_Client_declared
2#define joedb_Writable_Client_declared
3
6
7namespace joedb
8{
9 /// Writable specialization of Client
10 ///
11 /// @ingroup concurrency
12 class Writable_Client: public Client
13 {
14 friend class Client_Lock;
15
16 protected:
17 template<typename F> auto transaction(F transaction)
18 {
19 const Journal_Lock lock(get_writable_journal());
20
21 start_transaction();
22
23 using T = decltype(transaction());
24
25 if constexpr (std::is_void<T>::value)
26 {
27 try
28 {
30 do_checkpoint();
31 }
32 catch (...)
33 {
35 throw;
36 }
37
39 }
40 else
41 {
42 const T result = [&]()
43 {
44 try
45 {
46 const T inner_result = transaction();
47 do_checkpoint();
48 return inner_result;
49 }
50 catch (...)
51 {
53 throw;
54 }
55 } ();
56
58 return result;
59 }
60 }
61
62 private:
63 Writable_Journal &get_writable_journal()
64 {
65 return static_cast<Writable_Journal&>(Client::journal);
66 }
67
68 bool use_valid_data = false;
69 bool use_timestamp = false;
70 bool use_hard_checkpoint = false;
71
72 void do_checkpoint()
73 {
74 if (use_valid_data)
75 get_writable_journal().valid_data();
76
77 if (use_timestamp)
78 get_writable_journal().timestamp(std::time(nullptr));
79
80 get_writable_journal().soft_checkpoint();
81
82 if (use_hard_checkpoint)
83 get_writable_journal().hard_checkpoint();
84 }
85
86 void start_transaction()
87 {
89 (
92 get_writable_journal()
93 );
94
96 }
97
98 public:
100 (
103 Content_Check content_check = Content_Check::quick
104 ): Client(journal, connection, content_check)
105 {
106 }
107
108 /// Automatically write valid_data at every checkpoint (default = false)
109 void set_valid_data(bool b) {use_valid_data = b;}
110
111 /// Automatically write time stamp at every checkpoint (default = false)
112 void set_timestamp(bool b) {use_timestamp = b;}
113
114 /// Use hard checkpoints (default = false)
115 void set_hard_checkpoint(bool b) {use_hard_checkpoint = b;}
116
117 /// @param wait indicates how long the connection may wait for new data
118 ///
119 /// @retval pull_size number of bytes pulled
120 int64_t pull
121 (
122 std::chrono::milliseconds wait = std::chrono::milliseconds(0)
123 ) override
124 {
125 const int64_t old_checkpoint = get_journal_checkpoint();
126
127 const Journal_Lock lock(get_writable_journal());
128
130 (
133 get_writable_journal(),
134 wait
135 );
136
137 read_journal();
138
139 return get_journal_checkpoint() - old_checkpoint;
140 }
141
143 {
144 transaction([](){});
145 }
146
147 int64_t push_unlock()
148 {
150 }
151
152 int64_t push_if_ahead() override
153 {
155 return push_unlock();
156 else
158 }
159 };
160
161 /// Lock object that allows writing to a database managed by a joedb::Client
162 ///
163 /// At the end of the life of this object, right before destruction, you
164 /// should call either @ref unlock to cancel the transaction, or
165 /// @ref push_unlock to confirm it. If you fail to do so, the destructor
166 /// will call @ref unlock. But calling unlock explicitly is better,
167 /// if possible, because it can throw exceptions, unlike the destructor.
168 ///
169 /// @ingroup concurrency
171 {
172 protected:
175 bool locked;
176
177 public:
179 client(client),
180 journal_lock(client.get_writable_journal()),
181 locked(true)
182 {
183 client.start_transaction();
184 }
185
186 Client_Lock(const Client_Lock &) = delete;
188
189 /// Checkpoint current journal, but do not push yet
191 {
193 client.do_checkpoint();
194 }
195
196 /// Push if the journal checkpoint is ahead of the connection checkpoint
197 ///
198 /// This function keeps the connection locked
205
206 /// Checkpoint current journal, and push to the connection
207 ///
208 /// Unlike @ref push_unlock, you can call this function multiple
209 /// times during the life of the lock.
211 {
213 client.do_checkpoint();
215 }
216
217 /// Confirm the transaction right before lock destruction
218 ///
219 /// Destruction should happen right after this function.
220 /// Do not call any other member function after this one.
222 {
224 client.do_checkpoint();
226 locked = false;
227 }
228
229 /// Cancel the transaction right before lock destruction
230 ///
231 /// Destruction should happen right after this function.
232 /// Do not call any other member function after this one.
233 void unlock()
234 {
237 locked = false;
238 }
239
240 /// The destructor unlocks the connection if necessary
242 {
243 if (locked)
244 {
245 Destructor_Logger::write("locked in destructor, cancelling transaction");
246 try { unlock(); } catch (...) {}
247 }
248 }
249 };
250}
251
252#endif
Lock object that allows writing to a database managed by a joedb::Client.
void checkpoint_and_push_unlock()
Confirm the transaction right before lock destruction.
Writable_Client & client
void do_checkpoint()
Checkpoint current journal, but do not push yet.
void push_if_ahead()
Push if the journal checkpoint is ahead of the connection checkpoint.
Client_Lock(Writable_Client &client)
void checkpoint_and_push()
Checkpoint current journal, and push to the connection.
void unlock()
Cancel the transaction right before lock destruction.
Client_Lock(const Client_Lock &)=delete
~Client_Lock()
The destructor unlocks the connection if necessary.
const Journal_Lock journal_lock
Client_Lock & operator=(const Client_Lock &)=delete
Handle concurrent access to a file with a joedb::Connection.
Definition Client.h:12
virtual void read_journal()
Definition Client.h:14
int64_t connection_checkpoint
Definition Client.h:17
int64_t push(Unlock_Action unlock_action)
Definition Client.h:19
int64_t get_journal_checkpoint() const
Definition Client.h:62
Readonly_Journal & journal
Definition Client.h:15
Connection & connection
Definition Client.h:16
int64_t get_connection_checkpoint() const
Definition Client.h:72
virtual void unlock()
Unlock the connection.
virtual int64_t pull(Lock_Action lock_action, Data_Transfer data_transfer, Writable_Journal &client_journal, std::chrono::milliseconds wait=std::chrono::milliseconds(0))
Pull from the connection.
static void write(const char *message) noexcept
Writable specialization of Client.
void set_valid_data(bool b)
Automatically write valid_data at every checkpoint (default = false)
Writable_Client(Writable_Journal &journal, Connection &connection, Content_Check content_check=Content_Check::quick)
void set_hard_checkpoint(bool b)
Use hard checkpoints (default = false)
void set_timestamp(bool b)
Automatically write time stamp at every checkpoint (default = false)
int64_t pull(std::chrono::milliseconds wait=std::chrono::milliseconds(0)) override
int64_t push_if_ahead() override
auto transaction(F transaction)
void timestamp(int64_t timestamp) final
void hard_checkpoint()
Definition Writable.h:22
void soft_checkpoint()
Definition Writable.h:21
Content_Check
Definition Connection.h:19
#define JOEDB_DEBUG_ASSERT(x)
Definition assert.h:20
Definition Blob.h:7