Joedb 10.0.1
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);
118 interpreter.set_prompt_string("db");
119 run_interpreter(interpreter, in, out);
120 }
121 else
122 {
123 Command_Interpreter interpreter;
124 interpreter.set_prompt_string("db(blobs)");
125 run_interpreter(interpreter, in, out);
126 }
127 }
128 else if (command == "pull") ///////////////////////////////////////////////
129 {
130 float wait_seconds = 0;
131 parameters >> wait_seconds;
132 pull(out, std::chrono::milliseconds(std::lround(wait_seconds * 1000)));
133 }
134 else if (command == "pull_every") /////////////////////////////////////////
135 {
136 float wait_seconds = 1;
137 int sleep_seconds = 0;
138 parameters >> wait_seconds >> sleep_seconds;
139
142
143 while (Signal::get_signal() != SIGINT)
144 {
145 pull(out, std::chrono::milliseconds(std::lround(wait_seconds * 1000)));
146 sleep(sleep_seconds, out);
147 }
148 }
149 else if (command == "push" && !client.is_pullonly()) //////////////////////
150 {
151 client.push_if_ahead();
152 }
153 else if (command == "push_every" && !client.is_pullonly()) ////////////////
154 {
155 int sleep_seconds = 1;
156 parameters >> sleep_seconds;
157
160
161 while (Signal::get_signal() != SIGINT)
162 {
163 client.push_if_ahead();
164 sleep(sleep_seconds, out);
165 }
166 }
167 else //////////////////////////////////////////////////////////////////////
168 return Command_Interpreter::process_command(command, parameters, in, out);
170 return Status::done;
171 }
172
173 ////////////////////////////////////////////////////////////////////////////
175 ////////////////////////////////////////////////////////////////////////////
176 (
177 const std::string &command,
178 std::istream &parameters,
179 std::istream &in,
180 std::ostream &out
181 )
182 {
183 if (command == "help") ////////////////////////////////////////////////////
184 {
185 Client_Command_Processor::process_command(command, parameters, in, out);
186
187 out << R"RRR(Writable Client
188~~~~~~~~~~~~~~~
189 transaction
190 set_valid_data <true|false>
191 set_timestamp <true|false>
192 set_hard_checkpoint <true|false>
193
194)RRR";
195
196 return Status::ok;
197 }
198 else if (command == "transaction") ////////////////////////////////////////
199 {
200 auto * const wdc = dynamic_cast<Writable_Database_Client *>(&client);
201 auto * const wjc = dynamic_cast<Writable_Journal_Client *>(&client);
202
203 if (wdc)
204 {
205 wdc->transaction([&](const Readable &readable, Writable &writable)
206 {
207 Interpreter interpreter(readable, writable, Record_Id::null);
208 interpreter.set_prompt_string("transaction");
209 run_interpreter(interpreter, in, out);
210 });
211 }
212 else if (wjc)
213 {
214 wjc->transaction([&](Writable_Journal &journal)
215 {
216 Writable_Interpreter interpreter(journal);
217 interpreter.set_prompt_string("transaction(journal)");
218 run_interpreter(interpreter, in, out);
219 });
220 }
221 else
222 out << "Client is not writable, cannot run transaction\n";
223 }
224 else if (command == "set_valid_data") /////////////////////////////////////
225 {
226 get_writable_client().set_valid_data(read_boolean(parameters));
227 }
228 else if (command == "set_timestamp") //////////////////////////////////////
229 {
230 get_writable_client().set_timestamp(read_boolean(parameters));
231 }
232 else if (command == "set_hard_checkpoint") ////////////////////////////////
233 {
234 get_writable_client().set_hard_checkpoint(read_boolean(parameters));
235 }
236 else //////////////////////////////////////////////////////////////////////
237 return Client_Command_Processor::process_command(command, parameters, in, out);
238
239 return Status::done;
240 }
241}
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_prompt_string(std::string s)
Status process_command(const std::string &command, std::istream &parameters, std::istream &in, std::ostream &out) override
static const Record_Id null
Definition index_types.h:44
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