/src/tarantool/src/box/engine.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or |
5 | | * without modification, are permitted provided that the following |
6 | | * conditions are met: |
7 | | * |
8 | | * 1. Redistributions of source code must retain the above |
9 | | * copyright notice, this list of conditions and the |
10 | | * following disclaimer. |
11 | | * |
12 | | * 2. Redistributions in binary form must reproduce the above |
13 | | * copyright notice, this list of conditions and the following |
14 | | * disclaimer in the documentation and/or other materials |
15 | | * provided with the distribution. |
16 | | * |
17 | | * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND |
18 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
21 | | * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
22 | | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
25 | | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
26 | | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
28 | | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | | * SUCH DAMAGE. |
30 | | */ |
31 | | #include "engine.h" |
32 | | |
33 | | #include <stdbool.h> |
34 | | #include <stddef.h> |
35 | | #include <string.h> |
36 | | |
37 | | #include "errinj.h" |
38 | | #include "fiber.h" |
39 | | #include "small/rlist.h" |
40 | | |
41 | | RLIST_HEAD(engines); |
42 | | |
43 | | enum recovery_state recovery_state = RECOVERY_NOT_STARTED; |
44 | | |
45 | | /** Register engine instance. */ |
46 | | void engine_register(struct engine *engine) |
47 | 0 | { |
48 | 0 | static int n_engines; |
49 | 0 | rlist_add_tail_entry(&engines, engine, link); |
50 | 0 | engine->id = n_engines++; |
51 | 0 | } |
52 | | |
53 | | /** Find engine by name. */ |
54 | | struct engine * |
55 | | engine_by_name(const char *name) |
56 | 0 | { |
57 | 0 | struct engine *e; |
58 | 0 | engine_foreach(e) { |
59 | 0 | if (strcmp(e->name, name) == 0) |
60 | 0 | return e; |
61 | 0 | } |
62 | 0 | return NULL; |
63 | 0 | } |
64 | | |
65 | | void |
66 | | engine_shutdown(void) |
67 | 0 | { |
68 | 0 | struct engine *engine, *tmp; |
69 | 0 | rlist_foreach_entry_safe(engine, &engines, link, tmp) { |
70 | 0 | engine->vtab->shutdown(engine); |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | | void |
75 | | engine_free(void) |
76 | 0 | { |
77 | 0 | struct engine *engine, *tmp; |
78 | 0 | rlist_foreach_entry_safe(engine, &engines, link, tmp) { |
79 | 0 | engine->vtab->free(engine); |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | void |
84 | | engine_switch_to_ro(void) |
85 | 0 | { |
86 | 0 | struct engine *engine; |
87 | 0 | engine_foreach(engine) |
88 | 0 | engine->vtab->switch_to_ro(engine); |
89 | 0 | } |
90 | | |
91 | | int |
92 | | engine_bootstrap(void) |
93 | 0 | { |
94 | 0 | recovery_state = INITIAL_RECOVERY; |
95 | 0 | struct engine *engine; |
96 | 0 | engine_foreach(engine) { |
97 | 0 | if (engine->vtab->bootstrap(engine) != 0) |
98 | 0 | return -1; |
99 | 0 | } |
100 | 0 | recovery_state = FINISHED_RECOVERY; |
101 | 0 | return 0; |
102 | 0 | } |
103 | | |
104 | | int |
105 | | engine_begin_initial_recovery(const struct vclock *recovery_vclock) |
106 | 0 | { |
107 | 0 | recovery_state = INITIAL_RECOVERY; |
108 | 0 | struct engine *engine; |
109 | 0 | engine_foreach(engine) { |
110 | 0 | if (engine->vtab->begin_initial_recovery(engine, |
111 | 0 | recovery_vclock) != 0) |
112 | 0 | return -1; |
113 | 0 | } |
114 | 0 | return 0; |
115 | 0 | } |
116 | | |
117 | | int |
118 | | engine_begin_final_recovery(void) |
119 | 0 | { |
120 | 0 | recovery_state = FINAL_RECOVERY; |
121 | 0 | struct engine *engine; |
122 | 0 | engine_foreach(engine) { |
123 | 0 | if (engine->vtab->begin_final_recovery(engine) != 0) |
124 | 0 | return -1; |
125 | 0 | } |
126 | 0 | return 0; |
127 | 0 | } |
128 | | |
129 | | int |
130 | | engine_begin_hot_standby(void) |
131 | 0 | { |
132 | 0 | struct engine *engine; |
133 | 0 | engine_foreach(engine) { |
134 | 0 | if (engine->vtab->begin_hot_standby(engine) != 0) |
135 | 0 | return -1; |
136 | 0 | } |
137 | 0 | return 0; |
138 | 0 | } |
139 | | |
140 | | int |
141 | | engine_end_recovery(void) |
142 | 0 | { |
143 | 0 | recovery_state = FINISHED_RECOVERY; |
144 | | /* |
145 | | * For all new spaces created after recovery is complete, |
146 | | * when the primary key is added, enable all keys. |
147 | | */ |
148 | 0 | struct engine *engine; |
149 | 0 | engine_foreach(engine) { |
150 | 0 | if (engine->vtab->end_recovery(engine) != 0) |
151 | 0 | return -1; |
152 | 0 | } |
153 | 0 | return 0; |
154 | 0 | } |
155 | | |
156 | | int |
157 | | engine_begin_checkpoint(bool is_scheduled) |
158 | 0 | { |
159 | 0 | struct engine *engine; |
160 | 0 | engine_foreach(engine) { |
161 | 0 | if (engine->vtab->begin_checkpoint(engine, is_scheduled) < 0) |
162 | 0 | return -1; |
163 | 0 | } |
164 | 0 | return 0; |
165 | 0 | } |
166 | | |
167 | | int |
168 | | engine_commit_checkpoint(const struct vclock *vclock) |
169 | 0 | { |
170 | 0 | struct engine *engine; |
171 | 0 | engine_foreach(engine) { |
172 | 0 | if (engine->vtab->wait_checkpoint(engine, vclock) < 0) |
173 | 0 | return -1; |
174 | 0 | } |
175 | 0 | engine_foreach(engine) { |
176 | 0 | engine->vtab->commit_checkpoint(engine, vclock); |
177 | 0 | } |
178 | 0 | return 0; |
179 | 0 | } |
180 | | |
181 | | void |
182 | | engine_abort_checkpoint(void) |
183 | 0 | { |
184 | 0 | struct engine *engine; |
185 | 0 | engine_foreach(engine) |
186 | 0 | engine->vtab->abort_checkpoint(engine); |
187 | 0 | } |
188 | | |
189 | | void |
190 | | engine_collect_garbage(const struct vclock *vclock) |
191 | 0 | { |
192 | 0 | struct engine *engine; |
193 | 0 | engine_foreach(engine) |
194 | 0 | engine->vtab->collect_garbage(engine, vclock); |
195 | 0 | } |
196 | | |
197 | | int |
198 | | engine_backup(const struct vclock *vclock, engine_backup_cb cb, void *cb_arg) |
199 | 0 | { |
200 | 0 | struct engine *engine; |
201 | 0 | engine_foreach(engine) { |
202 | 0 | if (engine->vtab->backup(engine, vclock, cb, cb_arg) < 0) |
203 | 0 | return -1; |
204 | 0 | } |
205 | 0 | return 0; |
206 | 0 | } |
207 | | |
208 | | int |
209 | | engine_prepare_join(struct engine_join_ctx *ctx) |
210 | 0 | { |
211 | 0 | ctx->data = xcalloc(MAX_ENGINE_COUNT, sizeof(void *)); |
212 | 0 | struct engine *engine; |
213 | 0 | engine_foreach(engine) { |
214 | 0 | if (engine->vtab->prepare_join(engine, ctx) != 0) |
215 | 0 | goto fail; |
216 | 0 | } |
217 | 0 | return 0; |
218 | 0 | fail: |
219 | 0 | engine_complete_join(ctx); |
220 | 0 | return -1; |
221 | 0 | } |
222 | | |
223 | | int |
224 | | engine_join(struct engine_join_ctx *ctx, struct xstream *stream) |
225 | 0 | { |
226 | 0 | ERROR_INJECT_YIELD(ERRINJ_ENGINE_JOIN_DELAY); |
227 | | |
228 | 0 | struct engine *engine; |
229 | 0 | engine_foreach(engine) { |
230 | 0 | if (engine->vtab->join(engine, ctx, stream) != 0) |
231 | 0 | return -1; |
232 | 0 | } |
233 | 0 | return 0; |
234 | 0 | } |
235 | | |
236 | | void |
237 | | engine_complete_join(struct engine_join_ctx *ctx) |
238 | 0 | { |
239 | 0 | struct engine *engine; |
240 | 0 | engine_foreach(engine) { |
241 | 0 | engine->vtab->complete_join(engine, ctx); |
242 | 0 | } |
243 | 0 | free(ctx->data); |
244 | 0 | } |
245 | | |
246 | | void |
247 | | engine_memory_stat(struct engine_memory_stat *stat) |
248 | 0 | { |
249 | 0 | memset(stat, 0, sizeof(*stat)); |
250 | 0 | struct engine *engine; |
251 | 0 | engine_foreach(engine) |
252 | 0 | engine->vtab->memory_stat(engine, stat); |
253 | 0 | } |
254 | | |
255 | | void |
256 | | engine_reset_stat(void) |
257 | 0 | { |
258 | 0 | struct engine *engine; |
259 | 0 | engine_foreach(engine) |
260 | 0 | engine->vtab->reset_stat(engine); |
261 | 0 | } |
262 | | |
263 | | /* {{{ Virtual method stubs */ |
264 | | |
265 | | struct engine_read_view * |
266 | | generic_engine_create_read_view(struct engine *engine, |
267 | | const struct read_view_opts *opts) |
268 | 0 | { |
269 | 0 | (void)engine; |
270 | 0 | (void)opts; |
271 | 0 | unreachable(); |
272 | 0 | return NULL; |
273 | 0 | } |
274 | | |
275 | | int |
276 | | generic_engine_prepare_join(struct engine *engine, struct engine_join_ctx *ctx) |
277 | 0 | { |
278 | 0 | ctx->data[engine->id] = NULL; |
279 | 0 | return 0; |
280 | 0 | } |
281 | | |
282 | | int |
283 | | generic_engine_join(struct engine *engine, struct engine_join_ctx *ctx, |
284 | | struct xstream *stream) |
285 | 0 | { |
286 | 0 | (void)engine; |
287 | 0 | (void)ctx; |
288 | 0 | (void)stream; |
289 | 0 | return 0; |
290 | 0 | } |
291 | | |
292 | | void |
293 | | generic_engine_complete_join(struct engine *engine, struct engine_join_ctx *ctx) |
294 | 0 | { |
295 | 0 | (void)engine; |
296 | 0 | (void)ctx; |
297 | 0 | } |
298 | | |
299 | | int |
300 | | generic_engine_begin(struct engine *engine, struct txn *txn) |
301 | 0 | { |
302 | 0 | (void)engine; |
303 | 0 | (void)txn; |
304 | 0 | return 0; |
305 | 0 | } |
306 | | |
307 | | int |
308 | | generic_engine_begin_statement(struct engine *engine, struct txn *txn) |
309 | 0 | { |
310 | 0 | (void)engine; |
311 | 0 | (void)txn; |
312 | 0 | return 0; |
313 | 0 | } |
314 | | |
315 | | int |
316 | | generic_engine_prepare(struct engine *engine, struct txn *txn) |
317 | 0 | { |
318 | 0 | (void)engine; |
319 | 0 | (void)txn; |
320 | 0 | return 0; |
321 | 0 | } |
322 | | |
323 | | void |
324 | | generic_engine_commit(struct engine *engine, struct txn *txn) |
325 | 0 | { |
326 | 0 | (void)engine; |
327 | 0 | (void)txn; |
328 | 0 | } |
329 | | |
330 | | void |
331 | | generic_engine_rollback_statement(struct engine *engine, struct txn *txn, |
332 | | struct txn_stmt *stmt) |
333 | 0 | { |
334 | 0 | (void)engine; |
335 | 0 | (void)txn; |
336 | 0 | (void)stmt; |
337 | 0 | } |
338 | | |
339 | | void |
340 | | generic_engine_rollback(struct engine *engine, struct txn *txn) |
341 | 0 | { |
342 | 0 | (void)engine; |
343 | 0 | (void)txn; |
344 | 0 | } |
345 | | |
346 | | void |
347 | | generic_engine_switch_to_ro(struct engine *engine) |
348 | 0 | { |
349 | 0 | (void)engine; |
350 | 0 | } |
351 | | |
352 | | int |
353 | | generic_engine_bootstrap(struct engine *engine) |
354 | 0 | { |
355 | 0 | (void)engine; |
356 | 0 | return 0; |
357 | 0 | } |
358 | | |
359 | | int |
360 | | generic_engine_begin_initial_recovery(struct engine *engine, |
361 | | const struct vclock *vclock) |
362 | 0 | { |
363 | 0 | (void)engine; |
364 | 0 | (void)vclock; |
365 | 0 | return 0; |
366 | 0 | } |
367 | | |
368 | | int |
369 | | generic_engine_begin_final_recovery(struct engine *engine) |
370 | 0 | { |
371 | 0 | (void)engine; |
372 | 0 | return 0; |
373 | 0 | } |
374 | | |
375 | | int |
376 | | generic_engine_begin_hot_standby(struct engine *engine) |
377 | 0 | { |
378 | 0 | (void)engine; |
379 | 0 | return 0; |
380 | 0 | } |
381 | | |
382 | | int |
383 | | generic_engine_end_recovery(struct engine *engine) |
384 | 0 | { |
385 | 0 | (void)engine; |
386 | 0 | return 0; |
387 | 0 | } |
388 | | |
389 | | int |
390 | | generic_engine_begin_checkpoint(struct engine *engine, bool is_scheduled) |
391 | 0 | { |
392 | 0 | (void)engine; |
393 | 0 | (void)is_scheduled; |
394 | 0 | return 0; |
395 | 0 | } |
396 | | |
397 | | int |
398 | | generic_engine_wait_checkpoint(struct engine *engine, |
399 | | const struct vclock *vclock) |
400 | 0 | { |
401 | 0 | (void)engine; |
402 | 0 | (void)vclock; |
403 | 0 | return 0; |
404 | 0 | } |
405 | | |
406 | | void |
407 | | generic_engine_commit_checkpoint(struct engine *engine, |
408 | | const struct vclock *vclock) |
409 | 0 | { |
410 | 0 | (void)engine; |
411 | 0 | (void)vclock; |
412 | 0 | } |
413 | | |
414 | | void |
415 | | generic_engine_abort_checkpoint(struct engine *engine) |
416 | 0 | { |
417 | 0 | (void)engine; |
418 | 0 | } |
419 | | |
420 | | void |
421 | | generic_engine_collect_garbage(struct engine *engine, |
422 | | const struct vclock *vclock) |
423 | 0 | { |
424 | 0 | (void)engine; |
425 | 0 | (void)vclock; |
426 | 0 | } |
427 | | |
428 | | int |
429 | | generic_engine_backup(struct engine *engine, const struct vclock *vclock, |
430 | | engine_backup_cb cb, void *cb_arg) |
431 | 0 | { |
432 | 0 | (void)engine; |
433 | 0 | (void)vclock; |
434 | 0 | (void)cb; |
435 | 0 | (void)cb_arg; |
436 | 0 | return 0; |
437 | 0 | } |
438 | | |
439 | | void |
440 | | generic_engine_memory_stat(struct engine *engine, |
441 | | struct engine_memory_stat *stat) |
442 | 0 | { |
443 | 0 | (void)engine; |
444 | 0 | (void)stat; |
445 | 0 | } |
446 | | |
447 | | void |
448 | | generic_engine_reset_stat(struct engine *engine) |
449 | 0 | { |
450 | 0 | (void)engine; |
451 | 0 | } |
452 | | |
453 | | int |
454 | | generic_engine_check_space_def(struct space_def *def) |
455 | 0 | { |
456 | 0 | (void)def; |
457 | 0 | return 0; |
458 | 0 | } |
459 | | |
460 | | void |
461 | | generic_engine_shutdown(struct engine *engine) |
462 | 0 | { |
463 | 0 | (void)engine; |
464 | 0 | } |
465 | | |
466 | | /* }}} */ |