Joedb 10.2.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
joedbc.cpp
Go to the documentation of this file.
2#include "joedb/Multiplexer.h"
10
19
29
33
37
42
43#include <iostream>
44#include <filesystem>
45#include <regex>
46
47namespace joedb
48{
49 ////////////////////////////////////////////////////////////////////////////
51 ////////////////////////////////////////////////////////////////////////////
52 {
53 private:
54 std::vector<std::string> &names;
55
56 public:
57 explicit Custom_Collector(std::vector<std::string> &names): names(names)
58 {
59 }
60
61 void custom(const std::string &name) override
62 {
63 if (!is_identifier(name))
64 throw Exception("custom: invalid identifier");
65 names.emplace_back(name);
66 }
67 };
68
69 ////////////////////////////////////////////////////////////////////////////
70 static void compile
71 ////////////////////////////////////////////////////////////////////////////
72 (
73 Compiler_Options &options,
74 Compiler_Options *parent_options
75 )
76 {
77 const std::string joedbi_file_name = options.base_name + ".joedbi";
78 const std::string joedbc_file_name = options.base_name + ".joedbc";
79
80 //
81 // Read file.joedbi (write_lock to block concurrent invocations)
82 //
83 joedb::ifstream joedbi_file(joedbi_file_name, Open_Mode::write_lock);
84
85 {
86 Writable_Journal journal(options.schema_file);
87 Selective_Writable schema_writable(journal, Selective_Writable::schema);
88 Custom_Collector custom_collector(options.custom_names);
89
90 Multiplexer multiplexer{options.db, schema_writable, custom_collector};
91 Interpreter interpreter(options.db, multiplexer, Record_Id::null);
92 interpreter.set_echo(false);
93 interpreter.set_rethrow(true);
94 interpreter.main_loop(joedbi_file, std::cerr);
95 multiplexer.soft_checkpoint();
96 }
97
98 for (const auto &[tid, tname]: options.db.get_tables())
99 options.table_options[tid];
100
101 //
102 // Read file.joedbc
103 //
104 {
105 joedb::ifstream joedbc_file(joedbc_file_name, Open_Mode::read_existing);
106 parse_compiler_options(joedbc_file, options);
107 }
108
109 //
110 // Generate code
111 //
112 generator::Database_h(options).generate();
113 generator::Database_Writable_h(options).generate();
114 generator::Database_Writable_cpp(options).generate();
115 generator::Readonly_Database_h(options).generate();
116 generator::Types_h(options).generate();
117 generator::Readable_h(options).generate();
118
119 generator::readonly_h(options).generate();
120 generator::readonly_cpp(options).generate();
121
122 generator::Writable_Database_h(options).generate();
123 generator::Writable_Database_cpp(options).generate();
124 generator::File_Database_h(options).generate();
125 generator::Memory_Database_h(options).generate();
126 generator::Readonly_Interpreted_File_Database_h(options).generate();
127 generator::Interpreted_File_Database_h(options).generate();
128 generator::Multiplexer_h(options).generate();
129
130 generator::writable_h(options).generate();
131 generator::writable_cpp(options).generate();
132
133 generator::Client_h(options).generate();
134 generator::File_Client_h(options).generate();
135 generator::Readonly_Client_h(options).generate();
136
137 generator::ids_h(options, parent_options).generate();
138 generator::print_table_h(options).generate();
139
140 if (parent_options)
141 generator::Procedure_h(options, *parent_options).generate();
142 else
143 generator::Procedure_h(options, options).generate();
144
145 for (const auto &table: options.db.get_tables())
146 generator::introspection_h(options, table).generate();
147
148 //
149 // .gitignore
150 //
151 {
153 (
154 options.output_path + "/" + options.get_name_space_back() + "/.gitignore",
156 );
157 ofs << "*\n";
158 ofs.flush();
159 }
160 }
161
162 ////////////////////////////////////////////////////////////////////////////
163 static int joedbc(Arguments &arguments)
164 ////////////////////////////////////////////////////////////////////////////
165 {
166 const std::string_view base_name = arguments.get_next("<base_name>");
167
168 if (arguments.missing())
169 {
170 arguments.print_help(std::cerr);
171 std::cerr << "joedbc will read:\n";
172 std::cerr << " <base_name>.joedbi for the schema definition\n";
173 std::cerr << " <base_name>.joedbc for compiler options\n";
174 std::cerr << " <base_name>.rpc (optional) directory for RPC\n";
175 return 1;
176 }
177
178 Compiler_Options options;
179 options.exe_path = arguments[0];
180 options.output_path = ".";
181 options.base_name = std::string(base_name);
182
183 compile(options, nullptr);
184
185 //
186 // Generate code for procedure message schemas
187 //
188 {
189 std::error_code error_code;
190
191 std::filesystem::directory_iterator iterator
192 (
193 std::string(base_name) + ".rpc",
194 error_code
195 );
196
197 if (!error_code)
198 {
199 for (const auto &dir_entry: iterator)
200 {
201 if (dir_entry.path().extension() == ".joedbi")
202 {
203 auto path = dir_entry.path();
204 const std::string procedure_name = path.replace_extension("").string();
205
206 Compiler_Options procedure_options;
207 procedure_options.exe_path = arguments[0];
208 procedure_options.output_path = std::string(base_name) + "/rpc";
209 procedure_options.base_name = procedure_name;
210
211 compile(procedure_options, &options);
212 }
213 }
214 }
215 }
216
217 //
218 // Find list of procedures in Service.h
219 //
220 joedb::Memory_File memory_file;
221
222 try
223 {
224 joedb::File file
225 (
226 options.base_name + ".rpc/Service.h",
228 );
229 file.copy_to(memory_file);
230 }
231 catch (...)
232 {
233 }
234
235 if (memory_file.get_size())
236 {
237 std::filesystem::copy
238 (
239 options.base_name + ".rpc/Service.h",
240 options.base_name + "/rpc/Service.h",
241 std::filesystem::copy_options::overwrite_existing
242 );
243
244 const std::string &s = memory_file.get_data();
245
246 std::vector<generator::Procedure> procedures;
247
248 {
249 const std::regex pattern("void\\s+(\\w+)\\s*\\(\\s*(\\w+)\\s*::\\s*Writable_Database\\s*&\\s*\\w+\\s*\\)");
250
251 for
252 (
253 std::sregex_iterator i{s.begin(), s.end(), pattern};
254 i != std::sregex_iterator();
255 ++i
256 )
257 {
258 procedures.push_back({(*i)[1], (*i)[2]});
259 }
260 }
261
262 if (!procedures.empty())
263 {
264 generator::Procedures_h(options, procedures).generate();
265 generator::Signatures_h(options, procedures).generate();
266 generator::RPC_Client_h(options, procedures).generate();
267 }
268 }
269
270 return 0;
271 }
272}
273
274/////////////////////////////////////////////////////////////////////////////
275int main(int argc, char **argv)
276/////////////////////////////////////////////////////////////////////////////
277{
278 return joedb::main_wrapper(joedb::joedbc, argc, argv);
279}
void custom(const std::string &name) override
Definition joedbc.cpp:61
Custom_Collector(std::vector< std::string > &names)
Definition joedbc.cpp:57
Writable with empty insert_vector and delete_vector.
Definition Writable.h:120
std::string & get_data()
Definition Memory_File.h:23
int64_t get_size() const override
Get the size of the file, or -1 if it is unknown.
Definition Memory_File.h:27
static const Record_Id null
Definition index_types.h:44
int main()
void parse_compiler_options(std::istream &in, Compiler_Options &compiler_options)
bool is_identifier(const std::string &s)
@ truncate
create new file, or truncate existing file, and locks the file
@ write_lock
like write_existing_or_create_new, but waits instead of failing if already locked
@ read_existing
fails if does not exist
int main_wrapper(int(*main)(Arguments &), int argc, char **argv)
Process command-line arguments and catch exceptions from main.
JOEDB_FILE File
Definition File.h:25