Joedb 9.1.4
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Client.h
Go to the documentation of this file.
1#ifndef joedb_Client_declared
2#define joedb_Client_declared
3
6
7namespace joedb
8{
9 /// Handle concurrent access to a file with a joedb::Connection
10 /// @ingroup concurrency
11 class Client
12 {
13 friend class Client_Lock;
14
15 protected:
16 virtual void read_journal() = 0;
17
18 template<typename F> void transaction(F transaction)
19 {
20 Journal_Lock lock(*writable_journal);
21
22 start_transaction();
23
24 try
25 {
27 writable_journal->default_checkpoint();
28 }
29 catch (...)
30 {
31 connection.unlock();
32 throw;
33 }
34
36 }
37
38 private:
39 Readonly_Journal &readonly_journal;
40 Writable_Journal * const writable_journal;
41
42 Connection &connection;
43 int64_t server_checkpoint;
44
45 //////////////////////////////////////////////////////////////////////////
46 void push(bool unlock_after)
47 //////////////////////////////////////////////////////////////////////////
48 {
49 server_checkpoint = connection.push
50 (
51 readonly_journal,
52 server_checkpoint,
53 unlock_after
54 );
55 }
56
57 //////////////////////////////////////////////////////////////////////////
58 void push_and_keep_locked()
59 //////////////////////////////////////////////////////////////////////////
60 {
61 push(false);
62 }
63
64 //////////////////////////////////////////////////////////////////////////
65 void start_transaction()
66 //////////////////////////////////////////////////////////////////////////
67 {
68 server_checkpoint = connection.lock_pull(*writable_journal);
70 }
71
72 public:
73 //////////////////////////////////////////////////////////////////////////
75 //////////////////////////////////////////////////////////////////////////
76 (
77 Readonly_Journal &journal,
78 Connection &connection,
79 bool content_check = true
80 ):
81 readonly_journal(journal),
82 writable_journal(journal.get_writable_journal()),
83 connection(connection),
84 server_checkpoint
85 (
86 connection.handshake(journal, content_check)
87 )
88 {
89 }
90
91 bool is_readonly() const
92 {
93 return writable_journal == nullptr;
94 }
95
97 {
98 return readonly_journal;
99 }
100
101 int64_t get_checkpoint() const
102 {
104 }
105
106 std::string read_blob_data(Blob blob) const
107 {
108 return get_journal().get_file().read_blob_data(blob);
109 }
110
111 int64_t get_server_checkpoint() const
112 {
113 return server_checkpoint;
114 }
115
117 {
118 return get_checkpoint() - server_checkpoint;
119 }
120
121 /// @param wait indicates how long the connection may wait for new data
122 /// @retval pull_size number of bytes pulled
123 int64_t pull(std::chrono::milliseconds wait = std::chrono::milliseconds(0))
124 {
125 const int64_t old_checkpoint = get_checkpoint();
126
127 if (writable_journal)
128 {
129 Journal_Lock lock(*writable_journal);
130 server_checkpoint = connection.pull(*writable_journal, wait);
131 }
132 else
133 {
134 readonly_journal.pull();
135 server_checkpoint = connection.get_checkpoint(readonly_journal, wait);
136 }
137
138 read_journal();
139
140 return get_checkpoint() - old_checkpoint;
141 }
142
144 {
145 push(true);
146 }
147
148 virtual ~Client();
149 };
150
151 /// Lock object that allows writing to a database managed by a joedb::Client
152 ///
153 /// At the end of the life of this object, right before destruction, you
154 /// should call either @ref unlock to cancel the transaction, or
155 /// @ref push_unlock to confirm it. If you fail to do so, the destructor
156 /// will call @ref unlock. But calling unlock explicitly is better if possible,
157 /// because it can throw exceptions, unlike the destructor.
158 ///
159 /// @ingroup concurrency
161 {
162 private:
163 bool locked;
164
165 protected:
168 bool is_locked() const {return locked;}
169
170 public:
172 locked(true),
173 client(client),
174 journal_lock(*client.writable_journal)
175 {
176 client.start_transaction();
177 }
178
179 Client_Lock(const Client_Lock &) = delete;
181
182 /// Checkpoint current journal, and push to the connection
183 ///
184 /// Unlike @ref push_unlock, you can call this function multiple
185 /// times during the life of the lock.
186 void push()
187 {
189 client.writable_journal->default_checkpoint();
190 client.push_and_keep_locked();
191 }
192
193 /// Confirm the transaction right before lock destruction
194 ///
195 /// Destruction should happen right after this function.
196 /// Do not call any other member function after this one.
198 {
200 client.writable_journal->default_checkpoint();
202 locked = false;
203 }
204
205 /// Cancel the transaction right before lock destruction
206 ///
207 /// Destruction should happen right after this function.
208 /// Do not call any other member function after this one.
209 void unlock()
210 {
212 client.connection.unlock();
213 locked = false;
214 }
215
217 {
218 if (locked)
219 {
220 Destructor_Logger::write("locked in destructor, cancelling transaction");
221 try { unlock(); } catch (...) {}
222 }
223 }
224 };
225}
226
227#endif
virtual std::string read_blob_data(Blob blob) const
Lock object that allows writing to a database managed by a joedb::Client.
Definition Client.h:161
bool is_locked() const
Definition Client.h:168
Client & client
Definition Client.h:166
void push()
Checkpoint current journal, and push to the connection.
Definition Client.h:186
void unlock()
Cancel the transaction right before lock destruction.
Definition Client.h:209
Client_Lock(Client &client)
Definition Client.h:171
Client_Lock(const Client_Lock &)=delete
Client_Lock & operator=(const Client_Lock &)=delete
void push_unlock()
Confirm the transaction right before lock destruction.
Definition Client.h:197
Journal_Lock journal_lock
Definition Client.h:167
Handle concurrent access to a file with a joedb::Connection.
Definition Client.h:12
virtual void read_journal()=0
int64_t get_server_checkpoint() const
Definition Client.h:111
int64_t get_checkpoint() const
Definition Client.h:101
int64_t pull(std::chrono::milliseconds wait=std::chrono::milliseconds(0))
Definition Client.h:123
void transaction(F transaction)
Definition Client.h:18
const Readonly_Journal & get_journal() const
Definition Client.h:96
bool is_readonly() const
Definition Client.h:91
int64_t get_checkpoint_difference() const
Definition Client.h:116
std::string read_blob_data(Blob blob) const
Definition Client.h:106
virtual ~Client()
void push_unlock()
Definition Client.h:143
virtual int64_t pull(Writable_Journal &client_journal, std::chrono::milliseconds wait=std::chrono::milliseconds(0))
Pull new data from the connection.
int64_t push(Readonly_Journal &client_journal, int64_t from_checkpoint, bool unlock_after)
Shortcut to call push_until until the client checkpoint.
Definition Connection.h:67
virtual int64_t lock_pull(Writable_Journal &client_journal, std::chrono::milliseconds wait=std::chrono::milliseconds(0))
Fused lock_pull, executed at the start of a write transaction.
virtual void unlock()
Can be used to cancel a transaction without pushing.
virtual int64_t get_checkpoint(Readonly_Journal &client_journal, std::chrono::milliseconds wait=std::chrono::milliseconds(0))
Get new connection checkpoint without pulling.
static void write(const char *message) noexcept
int64_t get_checkpoint_position() const
const Buffered_File & get_file() const
void default_checkpoint()
Definition Writable.cpp:32
#define JOEDB_ASSERT(x)
Definition assert.h:18
Definition Blob.h:7