Joedb 9.6.2
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Client_Command_Processor.cpp
Go to the documentation of this file.
6#include "joedb/ui/type_io.h"
11#include "joedb/Signal.h"
12
13#include <thread>
14#include <chrono>
15#include <cmath>
16
17namespace joedb
18{
19 ////////////////////////////////////////////////////////////////////////////
20 void Client_Command_Processor::write_prompt(std::ostream &out) const
21 ////////////////////////////////////////////////////////////////////////////
22 {
23 out << get_name() << '(';
24
25 const int64_t journal_checkpoint = client.get_journal_checkpoint();
26 const int64_t connection_checkpoint = client.get_connection_checkpoint();
27 const int64_t diff = connection_checkpoint - journal_checkpoint;
28
29 out << journal_checkpoint;
30 if (diff > 0)
31 out << '+' << diff << ")(pull to sync)";
32 else if (diff < 0)
33 {
34 out << diff << ')';
35
36 if (client.is_pullonly())
37 out << "(cannot push)";
38 else
39 out << "(push to sync)";
40 }
41 else
42 out << ')';
43 }
44
45 ////////////////////////////////////////////////////////////////////////////
46 void Client_Command_Processor::pull
47 ////////////////////////////////////////////////////////////////////////////
48 (
49 std::ostream &out,
50 std::chrono::milliseconds wait
51 )
52 {
53 const int64_t byte_count = client.pull(wait);
54 if (byte_count > 0)
55 {
56 out << "pulled " << byte_count << " bytes, checkpoint = ";
57 out << client.get_journal_checkpoint() << '\n';
58 }
59 }
60
61 ////////////////////////////////////////////////////////////////////////////
62 void Client_Command_Processor::sleep(int seconds, std::ostream &out)
63 ////////////////////////////////////////////////////////////////////////////
64 {
65 if (seconds > 0)
66 {
68 out << ". Sleeping for " << seconds << " seconds...\n";
69 out.flush();
70 for (int i = seconds; Signal::get_signal() != SIGINT && --i >= 0;)
71 std::this_thread::sleep_for(std::chrono::seconds(1));
72 }
73 }
74
75 ////////////////////////////////////////////////////////////////////////////
77 ////////////////////////////////////////////////////////////////////////////
78 (
79 const std::string &command,
80 std::istream &parameters,
81 std::istream &in,
82 std::ostream &out
83 )
84 {
85 if (command == "help") ////////////////////////////////////////////////////
86 {
87 Command_Interpreter::process_command(command, parameters, in, out);
88
89 out << R"RRR(Client
90~~~~~~
91 db
92 pull [<wait_seconds>]
93 pull_every [<wait_seconds>] [<sleep_seconds>]
94)RRR";
95 if (!client.is_pullonly())
96 out << " push\n push_every [<sleep_seconds>]\n";
97 out << '\n';
98
99 return Status::ok;
100 }
101 else if (command == "db") /////////////////////////////////////////////////
102 {
103 const Database *database = nullptr;
104
105 {
106 auto * const rdc = dynamic_cast<Readonly_Database_Client *>(&client);
107 auto * const wdc = dynamic_cast<Writable_Database_Client *>(&client);
108
109 if (rdc)
110 database = &rdc->get_database();
111 else if (wdc)
112 database = &wdc->get_database();
113 }
114
115 if (database)
116 {
117 Readable_Interpreter interpreter(*database, &client.get_journal().get_file());
118 interpreter.set_parent(this);
119 interpreter.set_prompt_string("db");
120 interpreter.main_loop(in, out);
121 }
122 else
123 {
124 Command_Interpreter interpreter;
125 Blob_Reader_Command_Processor processor(client.get_journal().get_file());
126 interpreter.add_processor(processor);
127 interpreter.set_parent(this);
128 interpreter.set_prompt_string("db(blobs)");
129 interpreter.main_loop(in, out);
130 }
131 }
132 else if (command == "pull") ///////////////////////////////////////////////
133 {
134 float wait_seconds = 0;
135 parameters >> wait_seconds;
136 pull(out, std::chrono::milliseconds(std::lround(wait_seconds * 1000)));
137 }
138 else if (command == "pull_every") /////////////////////////////////////////
139 {
140 float wait_seconds = 1;
141 int sleep_seconds = 0;
142 parameters >> wait_seconds >> sleep_seconds;
143
146
147 while (Signal::get_signal() != SIGINT)
148 {
149 pull(out, std::chrono::milliseconds(std::lround(wait_seconds * 1000)));
150 sleep(sleep_seconds, out);
151 }
152 }
153 else if (command == "push" && !client.is_pullonly()) //////////////////////
154 {
155 client.push_if_ahead();
156 }
157 else if (command == "push_every" && !client.is_pullonly()) ////////////////
158 {
159 int sleep_seconds = 1;
160 parameters >> sleep_seconds;
161
164
165 while (Signal::get_signal() != SIGINT)
166 {
167 client.push_if_ahead();
168 sleep(sleep_seconds, out);
169 }
170 }
171 else //////////////////////////////////////////////////////////////////////
172 return Command_Interpreter::process_command(command, parameters, in, out);
174 return Status::done;
175 }
176
177 ////////////////////////////////////////////////////////////////////////////
179 ////////////////////////////////////////////////////////////////////////////
180 (
181 const std::string &command,
182 std::istream &parameters,
183 std::istream &in,
184 std::ostream &out
185 )
186 {
187 if (command == "help") ////////////////////////////////////////////////////
188 {
189 Client_Command_Processor::process_command(command, parameters, in, out);
190
191 out << R"RRR(Writable Client
192~~~~~~~~~~~~~~~
193 transaction
194 set_valid_data <true|false>
195 set_timestamp <true|false>
196 set_hard_checkpoint <true|false>
197
198)RRR";
199
200 return Status::ok;
201 }
202 else if (command == "transaction") ////////////////////////////////////////
203 {
204 auto * const wdc = dynamic_cast<Writable_Database_Client *>(&client);
205 auto * const wjc = dynamic_cast<Writable_Journal_Client *>(&client);
206
207 if (wdc)
208 {
209 wdc->transaction([&](const Readable &readable, Writable &writable)
210 {
211 Interpreter interpreter
212 (
213 readable,
214 writable,
215 &client.get_journal().get_file(),
216 writable,
217 0
218 );
219 interpreter.set_parent(this);
220 interpreter.set_prompt_string("transaction");
221 interpreter.main_loop(in, out);
222 });
223 }
224 else if (wjc)
225 {
226 wjc->transaction([&](Writable_Journal &journal)
227 {
228 Writable_Interpreter interpreter(journal, journal);
229 Blob_Reader_Command_Processor processor(journal.get_file());
230 interpreter.add_processor(processor);
231 interpreter.set_parent(this);
232 interpreter.set_prompt_string("transaction(journal)");
233 interpreter.main_loop(in, out);
234 });
235 }
236 else
237 out << "Client is not writable, cannot run transaction\n";
238 }
239 else if (command == "set_valid_data") /////////////////////////////////////
240 {
241 get_writable_client().set_valid_data(read_boolean(parameters));
242 }
243 else if (command == "set_timestamp") //////////////////////////////////////
244 {
245 get_writable_client().set_timestamp(read_boolean(parameters));
246 }
247 else if (command == "set_hard_checkpoint") ////////////////////////////////
248 {
249 get_writable_client().set_hard_checkpoint(read_boolean(parameters));
250 }
251 else //////////////////////////////////////////////////////////////////////
252 return Client_Command_Processor::process_command(command, parameters, in, out);
253
254 return Status::done;
255 }
256}
Status process_command(const std::string &command, std::istream &parameters, std::istream &in, std::ostream &out) override
void write_prompt(std::ostream &out) const override
static void sleep(int seconds, std::ostream &out)
void set_parent(const Command_Interpreter *new_parent)
void main_loop(std::istream &in, std::ostream &out)
void set_prompt_string(std::string s)
Status process_command(const std::string &command, std::istream &parameters, std::istream &in, std::ostream &out) override
void add_processor(Command_Processor &processor)
static int get_signal()
Definition Signal.cpp:27
static void start()
Definition Signal.cpp:34
static constexpr int no_signal
Definition Signal.h:16
static void set_signal(int status)
Definition Signal.cpp:20
Status process_command(const std::string &command, std::istream &parameters, std::istream &in, std::ostream &out) override
std::string get_time_string_of_now()
bool read_boolean(std::istream &in)
Definition type_io.cpp:215
Definition Blob.h:7