00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <jf/jf_config.h>
00021
00022
00023
00024
#ifdef HAVE_STDLIB_H
00025
# include <stdlib.h>
00026
#endif
00027
00028
#include <jf/jf_journal_recovery.h>
00029
#include <jf/jf_utils.h>
00030
#include <jf/jf_crash_simul.h>
00031
#include <jf_file.h>
00032
00033
00034
00035
00036
#ifdef JF_TRACE_MODULE
00037
# undef JF_TRACE_MODULE
00038
#endif
00039 #define JF_TRACE_MODULE JF_TRACE_MOD_LIB_JOURNAL_RECOVERY
00040
00041
00042
00043 void jf_journal_record_reset(
struct jf_journal_record_s *jr)
00044 {
00045 jr->
redo_code =
JF_JOURNAL_OP_CODE_NULL;
00046 jr->
redo_data = NULL;
00047 jr->
redo_data_alloc = 0;
00048 jr->
undo_code =
JF_JOURNAL_OP_CODE_NULL;
00049 jr->
undo_data = NULL;
00050 jr->
undo_data_alloc = 0;
00051 }
00052
00053
00054
00055 void jf_journal_record_destroy(
struct jf_journal_record_s *jr)
00056 {
00057
if (jr->
redo_data != NULL) {
00058 free(jr->
redo_data);
00059 jr->
redo_data = NULL;
00060 }
00061
if (jr->
undo_data != NULL) {
00062 free(jr->
undo_data);
00063 jr->
undo_data = NULL;
00064 }
00065
jf_journal_record_reset(jr);
00066 }
00067
00068
00069
00070 int jf_journal_analyze(
const char *path, uint32_t flags, FILE *out_stream)
00071 {
00072
enum Exception { FOPEN_ERROR
00073 , JOURNAL_LOAD
00074 , FSEEK_ERROR
00075 , JOURNAL_SCAN
00076 , NONE } excp;
00077
int ret_cod =
JF_RC_INTERNAL_ERROR;
00078 FILE *jrn_stream = NULL;
00079
00080
JF_TRACE((
"jf_journal_analyze\n"));
00081 TRY {
00082
jf_journal_t journal;
00083
00084
if (out_stream == NULL)
00085 out_stream = stdout;
00086
00087
00088
if (NULL == (jrn_stream = fopen(path,
"r+b")))
00089
THROW(FOPEN_ERROR);
00090
00091
00092
jf_journal_reset(&journal);
00093
00094
00095 ret_cod =
jf_journal_load(&journal, jrn_stream);
00096
if (
JF_RC_OK != ret_cod)
00097
THROW(JOURNAL_LOAD);
00098
00099
if (flags &
JF_JOURNAL_ANALYZE_TRACE) {
00100 fprintf(out_stream,
00101
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00102
"<journal>\n");
00103
jf_journal_trace(&journal,
"", out_stream);
00104 }
00105
00106
00107
if (flags &
JF_JOURNAL_ANALYZE_RECOVERY) {
00108
00109
jf_journal_file_t *jrn_jfile =
00110
jf_journal_file_tab_get_jfile(
00111 &(journal.
file_table),
00112
JF_JOURNAL_JOURNAL_FILE_ID);
00113
00114
if (0 !=
fseeko(
00115 jrn_stream,
jf_journal_file_get_last_pos(
00116 jrn_jfile),
00117 SEEK_SET))
00118
THROW(FSEEK_ERROR);
00119 }
00120
00121 ret_cod =
jf_journal_scan(&journal,
JF_JOURNAL_GLOBAL_FILE_ID,
00122 flags,
TRUE, out_stream);
00123
if (
JF_RC_OK != ret_cod)
00124
THROW(JOURNAL_SCAN);
00125
00126
if (flags &
JF_JOURNAL_ANALYZE_TRACE)
00127 fprintf(out_stream,
"</journal>\n");
00128
00129
THROW(NONE);
00130 }
CATCH {
00131
switch (excp) {
00132
case FOPEN_ERROR:
00133 ret_cod =
JF_RC_FOPEN_ERROR;
00134
break;
00135
case JOURNAL_LOAD:
00136
break;
00137
case FSEEK_ERROR:
00138
break;
00139
case JOURNAL_SCAN:
00140
break;
00141
case NONE:
00142 ret_cod =
JF_RC_OK;
00143
break;
00144
default:
00145 ret_cod =
JF_RC_INTERNAL_ERROR;
00146 }
00147
00148
00149
if (jrn_stream != NULL && 0 != fclose(jrn_stream) &&
00150 ret_cod >=
JF_RC_OK)
00151 ret_cod =
JF_RC_FCLOSE_ERROR;
00152
00153 }
00154
JF_TRACE((
"jf_journal_analyze/excp=%d/ret_cod=%d/errno=%d\n",
00155 excp, ret_cod, errno));
00156
return ret_cod;
00157 }
00158
00159
00160
00161 int jf_journal_scan(
jf_journal_t *journal,
jf_word_t file_id, uint32_t flags,
00162
int forward, FILE *out_stream)
00163 {
00164
enum Exception { REOPEN_FILES
00165 , FTELL_ERROR1
00166 , FTELL_ERROR2
00167 , SCAN_SEARCH
00168 , SCAN_REDO
00169 , SCAN_UNDO
00170 , INVALID_STATUS
00171 , TRACE_RECORD
00172 , INTERNAL_ERROR
00173 , ROLLBACK_ERROR
00174 , FTELL_ERROR3
00175 , FSEEK_ERROR
00176 , NONE } excp;
00177
int ret_cod =
JF_RC_INTERNAL_ERROR;
00178
00179
struct jf_journal_record_s jr;
00180
jf_journal_scan_status_t status =
00181 forward ?
JF_SCAN_SEARCH :
JF_SCAN_UNDO;
00182
00183
JF_TRACE((
"jf_journal_scan: file_id = " JF_WORD_T_FORMAT "\n",
00184 file_id));
00185
00186 TRY {
00187
jf_offset_t last_sync;
00188
00189 FILE *jrn_stream =
jf_journal_get_stream(journal);
00190
00191
00192
jf_journal_record_reset(&jr);
00193
00194
00195
if (
JF_RC_OK != (ret_cod =
jf_journal_reopen_files(journal)))
00196
THROW(REOPEN_FILES);
00197
00198
00199
00200
if (0 > (last_sync =
ftello(jrn_stream)))
00201
THROW(FTELL_ERROR1);
00202
00203
if (flags &
JF_JOURNAL_ANALYZE_TRACE)
00204 fprintf(out_stream,
" <records>\n");
00205
00206
while (
TRUE) {
00207
jf_offset_t journal_record_offset = 0;
00208
00209
if ((flags &
JF_JOURNAL_ANALYZE_TRACE) &&
00210 (0 > (journal_record_offset =
ftello(jrn_stream))))
00211
THROW(FTELL_ERROR2);
00212
00213
switch (status) {
00214
case JF_SCAN_SEARCH:
00215 ret_cod =
jf_journal_scan_search(
00216 journal, &jr, &status, last_sync,
00217 forward, flags);
00218
if (ret_cod !=
JF_RC_OK &&
00219 ret_cod !=
JF_RC_EOF)
00220
THROW(SCAN_SEARCH);
00221
break;
00222
case JF_SCAN_REDO:
00223 ret_cod =
jf_journal_scan_redo(
00224 journal, &jr, &status);
00225
if (ret_cod !=
JF_RC_OK &&
00226 ret_cod !=
JF_RC_EOF)
00227
THROW(SCAN_REDO);
00228
break;
00229
case JF_SCAN_UNDO:
00230 ret_cod =
jf_journal_scan_undo(
00231 journal, file_id, &jr, &status);
00232
if (ret_cod !=
JF_RC_OK &&
00233 ret_cod !=
JF_RC_EOF)
00234
THROW(SCAN_UNDO);
00235
break;
00236
case JF_SCAN_END:
00237
break;
00238
default:
00239
THROW(INVALID_STATUS);
00240 }
00241
00242
00243
if (
JF_RC_EOF == ret_cod)
00244
break;
00245
00246
if (flags &
JF_JOURNAL_ANALYZE_TRACE &&
00247
JF_RC_OK != (
00248 ret_cod =
jf_journal_trace_record(
00249 journal, &jr,
00250 journal_record_offset,
00251 out_stream, flags)))
00252
THROW(TRACE_RECORD);
00253 }
00254
00255
if (flags &
JF_JOURNAL_ANALYZE_TRACE)
00256 fprintf(out_stream,
" </records>\n");
00257
00258
00259
if (0 !=
fseeko(jrn_stream, last_sync, SEEK_SET))
00260
THROW(FSEEK_ERROR);
00261
00262
THROW(NONE);
00263 }
CATCH {
00264
switch (excp) {
00265
case REOPEN_FILES:
00266
break;
00267
case FTELL_ERROR1:
00268
case FTELL_ERROR2:
00269
case FTELL_ERROR3:
00270 ret_cod =
JF_RC_FTELL_ERROR;
00271
break;
00272
case SCAN_SEARCH:
00273
case SCAN_REDO:
00274
case SCAN_UNDO:
00275
break;
00276
case INVALID_STATUS:
00277 ret_cod =
JF_RC_INTERNAL_ERROR;
00278
break;
00279
case TRACE_RECORD:
00280
break;
00281
case INTERNAL_ERROR:
00282 ret_cod =
JF_RC_INTERNAL_ERROR;
00283
break;
00284
case ROLLBACK_ERROR:
00285
break;
00286
case FSEEK_ERROR:
00287 ret_cod =
JF_RC_FSEEK_ERROR;
00288
break;
00289
case NONE:
00290 ret_cod =
JF_RC_OK;
00291
break;
00292
default:
00293 ret_cod =
JF_RC_INTERNAL_ERROR;
00294 }
00295
00296
00297
jf_journal_record_destroy(&jr);
00298
00299 }
00300
JF_TRACE((
"jf_journal_scan/excp=%d/ret_cod=%d/errno=%d\n",
00301 excp, ret_cod, errno));
00302
return ret_cod;
00303 }
00304
00305
00306
00307 int jf_journal_scan_search(
jf_journal_t *journal,
00308
struct jf_journal_record_s *jr,
00309 jf_journal_scan_status_t *status,
00310
jf_offset_t last_sync,
int forward, uint32_t flags)
00311 {
00312
enum Exception { END_OF_FILE
00313 , FETCH_RECORD
00314 , SKIP_RECORD
00315 , FSEEK_ERROR1
00316 , FSEEK_ERROR2
00317 , SET_ALL_IN_CACHE
00318 , NONE } excp;
00319
int ret_cod =
JF_RC_INTERNAL_ERROR;
00320
00321
JF_TRACE((
"jf_journal_scan_search\n"));
00322 TRY {
00323 FILE *jrn_stream =
jf_journal_get_stream(journal);
00324
jf_word_t ctrl_code,
id;
00325
00326 ret_cod =
jf_journal_fetch_record(journal, jr, forward);
00327
if (ret_cod ==
JF_RC_EOF) {
00328
THROW(END_OF_FILE);
00329 }
else if (ret_cod !=
JF_RC_OK)
00330
THROW(FETCH_RECORD);
00331
00332
if (!(flags &
JF_JOURNAL_ANALYZE_RECOVERY))
00333
THROW(SKIP_RECORD);
00334
00335
00336
if (forward) {
00337 ctrl_code = jr->
redo_code &
JF_JOURNAL_OP_MASK;
00338
id = (jr->
redo_code & journal->
file_id_mask) >>
00339 journal->
file_id_mask_shift;
00340 }
else {
00341 ctrl_code = jr->
undo_code &
JF_JOURNAL_OP_MASK;
00342
id = (jr->
undo_code & journal->
file_id_mask) >>
00343 journal->
file_id_mask_shift;
00344 }
00345
switch (ctrl_code) {
00346
case JF_JOURNAL_OP_CODE_COMMIT:
00347
00348
JF_TRACE((
"jf_journal_scan_search: "
00349
"found COMMIT record\n"));
00350
if (0 !=
fseeko(jrn_stream, last_sync,
00351 SEEK_SET))
00352
THROW(FSEEK_ERROR1);
00353
if (forward)
00354 *status =
JF_SCAN_REDO;
00355
else
00356 *status =
JF_SCAN_UNDO;
00357
break;
00358
case JF_JOURNAL_OP_CODE_ROLLBACK:
00359
00360
JF_TRACE((
"jf_journal_scan_search: "
00361
"found ROLLBACK record\n"));
00362
if (0 !=
fseeko(
00363 jrn_stream,
00364 -((
jf_offset_t)
sizeof(
jf_word_t)),
00365 SEEK_CUR))
00366
THROW(FSEEK_ERROR2);
00367 *status =
JF_SCAN_UNDO;
00368
break;
00369
default:
00370
break;
00371 }
00372
00373
THROW(NONE);
00374 }
CATCH {
00375
switch (excp) {
00376
case END_OF_FILE:
00377
break;
00378
case FETCH_RECORD:
00379
break;
00380
case SKIP_RECORD:
00381 ret_cod =
JF_RC_OK;
00382
break;
00383
case FSEEK_ERROR1:
00384
case FSEEK_ERROR2:
00385 ret_cod =
JF_RC_FSEEK_ERROR;
00386
break;
00387
case SET_ALL_IN_CACHE:
00388
break;
00389
case NONE:
00390 ret_cod =
JF_RC_OK;
00391
break;
00392
default:
00393 ret_cod =
JF_RC_INTERNAL_ERROR;
00394 }
00395 }
00396
JF_TRACE((
"jf_journal_scan_search/excp=%d/ret_cod=%d/"
00397
"errno=%d\n", excp, ret_cod, errno));
00398
return ret_cod;
00399 }
00400
00401
00402
00403 int jf_journal_scan_redo(
jf_journal_t *journal,
00404
struct jf_journal_record_s *jr,
00405 jf_journal_scan_status_t *status)
00406 {
00407
enum Exception { END_OF_FILE
00408 , FETCH_RECORD
00409 , INVALID_STATUS
00410 , APPLY_CHANGES
00411 , NONE } excp;
00412
int ret_cod =
JF_RC_INTERNAL_ERROR;
00413
00414
JF_TRACE((
"jf_journal_scan_redo\n"));
00415 TRY {
00416
jf_word_t ctrl_code;
00417
00418 ret_cod =
jf_journal_fetch_record(journal, jr,
TRUE);
00419
if (ret_cod ==
JF_RC_EOF) {
00420
THROW(END_OF_FILE);
00421 }
else if (ret_cod !=
JF_RC_OK)
00422
THROW(FETCH_RECORD);
00423
00424 ctrl_code = jr->
redo_code &
JF_JOURNAL_OP_MASK;
00425
switch (ctrl_code) {
00426
case JF_JOURNAL_OP_CODE_COMMIT:
00427
break;
00428
case JF_JOURNAL_OP_CODE_ROLLBACK:
00429
THROW(INVALID_STATUS);
00430
break;
00431
default:
00432 ret_cod =
jf_journal_apply_changes(journal, jr);
00433
if (
JF_RC_OK != ret_cod)
00434
THROW(APPLY_CHANGES);
00435
break;
00436 }
00437
00438
THROW(NONE);
00439 }
CATCH {
00440
switch (excp) {
00441
case END_OF_FILE:
00442
break;
00443
case FETCH_RECORD:
00444
break;
00445
case INVALID_STATUS:
00446 ret_cod =
JF_RC_INTERNAL_ERROR;
00447
break;
00448
case APPLY_CHANGES:
00449
break;
00450
case NONE:
00451 ret_cod =
JF_RC_OK;
00452
break;
00453
default:
00454 ret_cod =
JF_RC_INTERNAL_ERROR;
00455 }
00456 }
00457
JF_TRACE((
"jf_journal_scan_redo/excp=%d/ret_cod=%d/errno=%d\n",
00458 excp, ret_cod, errno));
00459
return ret_cod;
00460 }
00461
00462
00463
00464 int jf_journal_scan_undo(
jf_journal_t *journal,
jf_word_t rec_file_id,
00465
struct jf_journal_record_s *jr,
00466 jf_journal_scan_status_t *status)
00467 {
00468
enum Exception { END_OF_FILE1
00469 , FETCH_RECORD
00470 , SET_ALL_SYNC1
00471 , FILE_SET_STATUS0
00472 , FILE_SET_STATUS1
00473 , END_OF_FILE2
00474 , END_OF_FILE3
00475 , FILE_SET_ALL_IN_CACHE
00476 , INVALID_STATUS
00477 , FSEEK_ERROR1
00478 , SET_ALL_SYNC2
00479 , FILE_SET_STATUS2
00480 , END_OF_FILE4
00481 , END_OF_FILE5
00482 , FSEEK_ERROR2
00483 , SKIP_RECORD
00484 , APPLY_CHANGES
00485 , NONE } excp;
00486
int ret_cod =
JF_RC_INTERNAL_ERROR;
00487
00488
JF_TRACE((
"jf_journal_scan_undo\n"));
00489 TRY {
00490
jf_word_t ctrl_code;
00491
jf_word_t jr_file_id;
00492
jf_journal_file_t *jfile = NULL, *rec_file = NULL;
00493 FILE *jrn_stream = NULL;
00494
00495 ret_cod =
jf_journal_fetch_record(journal, jr,
FALSE);
00496
if (ret_cod ==
JF_RC_EOF) {
00497
THROW(END_OF_FILE1);
00498 }
else if (ret_cod !=
JF_RC_OK)
00499
THROW(FETCH_RECORD);
00500
00501
00502 ctrl_code = jr->
undo_code &
JF_JOURNAL_OP_MASK;
00503 jr_file_id = (jr->
undo_code & journal->
file_id_mask) >>
00504 journal->
file_id_mask_shift;
00505 jfile =
jf_journal_file_tab_get_jfile(
00506 &(journal->
file_table), jr_file_id);
00507
00508
JF_TRACE((
"jf_journal_scan_undo: "
00509
"jr_file_id = " JF_WORD_T_FORMAT ", "
00510
"rec_file_id = " JF_WORD_T_FORMAT "\n",
00511 jr_file_id, rec_file_id));
00512
00513
switch (ctrl_code) {
00514
case JF_JOURNAL_OP_CODE_COMMIT:
00515
JF_TRACE((
"jf_journal_scan_undo: "
00516
"JF_JOURNAL_OP_CODE_COMMIT\n"));
00517
if (jr_file_id ==
JF_JOURNAL_GLOBAL_FILE_ID) {
00518
JF_TRACE((
"jf_journal_scan_undo: "
00519
"JF_JOURNAL_OP_CODE_COMMIT, "
00520
"jr_file_id == "
00521
"JF_JOURNAL_GLOBAL_FILE_ID\n"));
00522
if (jr_file_id == rec_file_id) {
00523
JF_TRACE((
"jf_journal_scan_undo: "
00524
"JF_JOURNAL_OP_CODE_COMMIT, "
00525
"jr_file_id == "
00526
"JF_JOURNAL_GLOBAL_FILE_ID, "
00527
"jr_file_id == "
00528
"rec_file_id\n"));
00529 ret_cod =
jf_journal_set_all_sync(
00530 journal);
00531
if (
JF_RC_OK != ret_cod)
00532
THROW(SET_ALL_SYNC1);
00533 }
else {
00534
JF_TRACE((
"jf_journal_scan_undo: "
00535
"JF_JOURNAL_OP_CODE_COMMIT, "
00536
"jr_file_id == "
00537
"JF_JOURNAL_GLOBAL_FILE_ID, "
00538
"jr_file_id != "
00539
"rec_file_id\n"));
00540 rec_file =
jf_journal_file_tab_get_jfile(
00541 &(journal->
file_table),
00542 rec_file_id);
00543 ret_cod =
jf_journal_file_set_status(
00544 rec_file,
00545
jf_journal_file_get_status(
00546 rec_file) |
00547
JF_JOURNAL_FILE_ST_SYNC);
00548
if (
JF_RC_OK != ret_cod)
00549
THROW(FILE_SET_STATUS0);
00550 }
00551 }
else {
00552
JF_TRACE((
"jf_journal_scan_undo: "
00553
"JF_JOURNAL_OP_CODE_COMMIT, "
00554
"jr_file_id != "
00555
"JF_JOURNAL_GLOBAL_FILE_ID\n"));
00556
if (jr_file_id == rec_file_id ||
00557 rec_file_id ==
JF_JOURNAL_GLOBAL_FILE_ID) {
00558
JF_TRACE((
"jf_journal_scan_undo: "
00559
"JF_JOURNAL_OP_CODE_COMMIT, "
00560
"jr_file_id != "
00561
"JF_JOURNAL_GLOBAL_FILE_ID, "
00562
"jr_file_id == "
00563
"rec_file_id\n"));
00564
JF_TRACE((
"jf_journal_scan_undo: "
00565
"jr_file_id = "
00566
JF_WORD_T_FORMAT
00567
", status = "
00568
JF_WORD_T_FORMAT "\n",
00569 jr_file_id,
00570
jf_journal_file_get_status(
00571 jfile)));
00572 ret_cod =
jf_journal_file_set_status(
00573 jfile,
00574
jf_journal_file_get_status(
00575 jfile) |
00576
JF_JOURNAL_FILE_ST_SYNC);
00577
if (
JF_RC_OK != ret_cod)
00578
THROW(FILE_SET_STATUS1);
00579
JF_TRACE((
"jf_journal_scan_undo: "
00580
"jr_file_id = "
00581
JF_WORD_T_FORMAT
00582
", status = "
00583
JF_WORD_T_FORMAT "\n",
00584 jr_file_id,
00585
jf_journal_file_get_status(
00586 jfile)));
00587
00588
if ((jr_file_id == rec_file_id &&
00589
jf_journal_file_get_status(
00590 jfile) &
00591
JF_JOURNAL_FILE_ST_SYNC))
00592
THROW(END_OF_FILE2);
00593 }
00594 }
00595
if (
jf_journal_is_sync(journal, rec_file_id))
00596
THROW(END_OF_FILE3);
00597
00598 jrn_stream =
jf_journal_get_stream(journal);
00599
if (0 !=
fseeko(jrn_stream,
00600 -((
jf_offset_t)
sizeof(ctrl_code)),
00601 SEEK_CUR))
00602
THROW(FSEEK_ERROR1);
00603
break;
00604
case JF_JOURNAL_OP_CODE_ROLLBACK:
00605
JF_TRACE((
"jf_journal_scan_undo: "
00606
"JF_JOURNAL_OP_CODE_ROLLBACK\n"));
00607
if (jr_file_id ==
JF_JOURNAL_GLOBAL_FILE_ID) {
00608
JF_TRACE((
"jf_journal_scan_undo: "
00609
"JF_JOURNAL_OP_CODE_ROLLBACK, "
00610
"jr_file_id == "
00611
"JF_JOURNAL_GLOBAL_FILE_ID\n"));
00612
if (jr_file_id == rec_file_id) {
00613
JF_TRACE((
"jf_journal_scan_undo: "
00614
"JF_JOURNAL_OP_CODE_ROLLBACK"
00615
", jr_file_id == "
00616
"JF_JOURNAL_GLOBAL_FILE_ID "
00617
"jr_file_id == "
00618
"rec_file_id\n"));
00619 ret_cod =
jf_journal_set_all_sync(
00620 journal);
00621
if (
JF_RC_OK != ret_cod)
00622
THROW(SET_ALL_SYNC2);
00623 }
else {
00624
JF_TRACE((
"jf_journal_scan_undo: "
00625
"JF_JOURNAL_OP_CODE_ROLLBACK"
00626
", jr_file_id == "
00627
"JF_JOURNAL_GLOBAL_FILE_ID "
00628
"jr_file_id != "
00629
"rec_file_id\n"));
00630
JF_TRACE((
"jf_journal_scan_undo: "
00631
"jr_file_id = "
00632
JF_WORD_T_FORMAT
00633
", status = "
00634
JF_WORD_T_FORMAT
00635
"\n", jr_file_id,
00636
jf_journal_file_get_status(
00637 jfile)));
00638 ret_cod =
jf_journal_file_set_status(
00639 jfile,
00640
jf_journal_file_get_status(
00641 jfile) |
00642
JF_JOURNAL_FILE_ST_SYNC);
00643
if (
JF_RC_OK != ret_cod)
00644
THROW(FILE_SET_STATUS2);
00645
JF_TRACE((
"jf_journal_scan_undo: "
00646
"jr_file_id = "
00647
JF_WORD_T_FORMAT
00648
", status = "
00649
JF_WORD_T_FORMAT "\n",
00650 jr_file_id,
00651
jf_journal_file_get_status(
00652 jfile)));
00653 }
00654 }
else {
00655
JF_TRACE((
"jf_journal_scan_undo: "
00656
"JF_JOURNAL_OP_CODE_ROLLBACK, "
00657
"jr_file_id != "
00658
"JF_JOURNAL_GLOBAL_FILE_ID\n"));
00659
if (jr_file_id == rec_file_id) {
00660
JF_TRACE((
"jf_journal_scan_undo: "
00661
"JF_JOURNAL_OP_CODE_ROLLBACK"
00662
", jr_file_id != "
00663
"JF_JOURNAL_GLOBAL_FILE_ID"
00664
"jr_file_id == "
00665
"rec_file_id\n"));
00666
JF_TRACE((
"jf_journal_scan_undo: "
00667
"jr_file_id = "
00668
JF_WORD_T_FORMAT
00669
", status = "
00670
JF_WORD_T_FORMAT
00671
"\n", jr_file_id,
00672
jf_journal_file_get_status(
00673 jfile)));
00674 ret_cod =
jf_journal_file_set_status(
00675 jfile,
00676
jf_journal_file_get_status(
00677 jfile) |
00678
JF_JOURNAL_FILE_ST_SYNC);
00679
if (
JF_RC_OK != ret_cod)
00680
THROW(FILE_SET_STATUS2);
00681
JF_TRACE((
"jf_journal_scan_undo: "
00682
"jr_file_id = "
00683
JF_WORD_T_FORMAT
00684
", status = "
00685
JF_WORD_T_FORMAT "\n",
00686 jr_file_id,
00687
jf_journal_file_get_status(
00688 jfile)));
00689 }
00690
00691
if ((jr_file_id == rec_file_id &&
00692
jf_journal_file_get_status(jfile) &
00693
JF_JOURNAL_FILE_ST_SYNC))
00694
THROW(END_OF_FILE4);
00695 }
00696
if (
jf_journal_is_sync(journal, rec_file_id))
00697
THROW(END_OF_FILE5);
00698
00699 jrn_stream =
jf_journal_get_stream(journal);
00700
if (0 !=
fseeko(jrn_stream,
00701 -((
jf_offset_t)
sizeof(ctrl_code)),
00702 SEEK_CUR))
00703
THROW(FSEEK_ERROR2);
00704
break;
00705
default:
00706
if ((rec_file_id !=
JF_JOURNAL_GLOBAL_FILE_ID &&
00707 jr_file_id != rec_file_id))
00708
THROW(SKIP_RECORD);
00709 ret_cod =
jf_journal_remove_changes(journal, jr);
00710
if (
JF_RC_OK != ret_cod)
00711
THROW(APPLY_CHANGES);
00712
break;
00713 }
00714
00715
THROW(NONE);
00716 }
CATCH {
00717
switch (excp) {
00718
case END_OF_FILE1:
00719
case END_OF_FILE2:
00720
case END_OF_FILE3:
00721
case END_OF_FILE4:
00722
case END_OF_FILE5:
00723 ret_cod =
JF_RC_EOF;
00724
break;
00725
case FETCH_RECORD:
00726
case SET_ALL_SYNC1:
00727
case SET_ALL_SYNC2:
00728
case FILE_SET_ALL_IN_CACHE:
00729
case FILE_SET_STATUS0:
00730
case FILE_SET_STATUS1:
00731
case FILE_SET_STATUS2:
00732
case APPLY_CHANGES:
00733
break;
00734
case INVALID_STATUS:
00735 ret_cod =
JF_RC_INTERNAL_ERROR;
00736
break;
00737
case FSEEK_ERROR1:
00738
case FSEEK_ERROR2:
00739 ret_cod =
JF_RC_FSEEK_ERROR;
00740
break;
00741
case SKIP_RECORD:
00742
case NONE:
00743 ret_cod =
JF_RC_OK;
00744
break;
00745
default:
00746 ret_cod =
JF_RC_INTERNAL_ERROR;
00747 }
00748 }
00749
JF_TRACE((
"jf_journal_scan_undo/excp=%d/ret_cod=%d/errno=%d\n",
00750 excp, ret_cod, errno));
00751
return ret_cod;
00752 }
00753
00754
00755
00756 int jf_journal_reopen_files(
jf_journal_t *journal)
00757 {
00758
enum Exception { FILE_OPEN_STREAM
00759 , NONE } excp;
00760
int ret_cod =
JF_RC_INTERNAL_ERROR;
00761
00762
JF_TRACE((
"jf_journal_reopen_files\n"));
00763 TRY {
00764
jf_word_t nof =
jf_journal_file_tab_get_number_of_files(
00765 &(journal->
file_table));
00766
jf_word_t i;
00767
00768
for (i = 0; i < nof; ++i) {
00769
const jf_journal_file_t *jfile =
00770
jf_journal_file_tab_get_jfile(
00771 &(journal->
file_table), i);
00772 FILE *stream =
jf_journal_file_get_stream(jfile);
00773
00774
if (stream == NULL &&
00775
jf_journal_file_get_status(jfile) &
00776
JF_JOURNAL_FILE_ST_OPEN) {
00777
jf_file_t jf;
00778
00779 ret_cod =
jf_file_open(
00780 &jf, journal,
00781
jf_journal_file_get_path(jfile),
00782
"r+", NULL);
00783
if (
JF_RC_OK != ret_cod)
00784
THROW(FILE_OPEN_STREAM);
00785 }
00786 }
00787
00788
THROW(NONE);
00789 }
CATCH {
00790
switch (excp) {
00791
case FILE_OPEN_STREAM:
00792
break;
00793
case NONE:
00794 ret_cod =
JF_RC_OK;
00795
break;
00796
default:
00797 ret_cod =
JF_RC_INTERNAL_ERROR;
00798 }
00799 }
00800
JF_TRACE((
"jf_journal_reopen_files/excp=%d/ret_cod=%d/"
00801
"errno=%d\n", excp, ret_cod, errno));
00802
return ret_cod;
00803 }
00804
00805
00806
00807 int jf_journal_fetch_record(
const jf_journal_t *journal,
00808
struct jf_journal_record_s *jr,
int forward)
00809 {
00810
enum Exception { EOF_REACHED1
00811 , FSEEK_ERROR1
00812 , FTELL_ERROR1
00813 , EOF_REACHED2
00814 , INVALID_STREAM_POSITION
00815 , EOF_REACHED3
00816 , FREAD_ERROR1
00817 , INVALID_REDO_UNDO_FLAG1
00818 , INVALID_OPERATOR_CODE1
00819 , REALLOC_ERROR1
00820 , REALLOC_ERROR2
00821 , FSEEK_ERROR2
00822 , FREAD_ERROR2
00823 , REALLOC_ERROR3
00824 , REALLOC_ERROR4
00825 , FSEEK_ERROR3
00826 , FREAD_ERROR3
00827 , FSEEK_ERROR4
00828 , FSEEK_ERROR5
00829 , FSEEK_ERROR6
00830 , FSEEK_ERROR7
00831 , FSEEK_ERROR8
00832 , FREAD_ERROR4
00833 , FREAD_ERROR5
00834 , FREAD_ERROR6
00835 , INVALID_REDO_UNDO_FLAG2
00836 , INVALID_OPERATOR_CODE2
00837 , NONE } excp;
00838
int ret_cod =
JF_RC_INTERNAL_ERROR;
00839
00840
JF_TRACE((
"jf_journal_fetch_record\n"));
00841 TRY {
00842
byte_t *tmp_data = NULL;
00843
jf_word_t ctrl_code, op, size;
00844 FILE *jrn_stream =
jf_journal_get_stream(journal);
00845
00846
if (forward) {
00847
if (feof(jrn_stream))
00848
THROW(EOF_REACHED1);
00849 }
else {
00850
jf_offset_t curr_pos;
00851
00852
if (0 !=
fseeko(jrn_stream,
00853 -((
jf_offset_t)
sizeof(ctrl_code)),
00854 SEEK_CUR))
00855
THROW(FSEEK_ERROR1);
00856
if (0 > (curr_pos =
ftello(jrn_stream)))
00857
THROW(FTELL_ERROR1);
00858
if (curr_pos <= journal->
journal_recs) {
00859
THROW(EOF_REACHED2);
00860 }
else if (curr_pos == journal->
journal_recs)
00861
THROW(INVALID_STREAM_POSITION);
00862 }
00863
00864
JF_TRACE((
"jf_journal_fetch_record: curr_pos = "
00865
JF_OFFSET_T_FORMAT "\n",
ftello(jrn_stream)));
00866
00867
00868 jr->
redo_code = jr->
undo_code =
JF_JOURNAL_OP_CODE_NULL;
00869
00870
00871
if (1 != fread(&ctrl_code,
sizeof(ctrl_code), 1, jrn_stream)) {
00872
if (feof(jrn_stream)) {
00873
THROW(EOF_REACHED3);
00874 }
else {
00875
THROW(FREAD_ERROR1);
00876 }
00877 }
00878
00879
JF_TRACE((
"jf_journal_fetch_record: code = %X (%s)\n",
00880 ctrl_code,
jf_journal_describe_code(ctrl_code)));
00881
00882
if (forward)
00883 jr->
redo_code = ctrl_code;
00884
else
00885 jr->
undo_code = ctrl_code;
00886
00887
00888 op = ctrl_code &
JF_JOURNAL_OP_MASK;
00889
00890 size = (ctrl_code & journal->
size_mask) >>
00891 journal->
size_mask_shift;
00892
00893
00894 ctrl_code &=
JF_JOURNAL_OP_CODE_MASK;
00895
00896
switch (ctrl_code) {
00897
case JF_JOURNAL_OP_CODE_APPEND:
00898
case JF_JOURNAL_OP_CODE_UPDATE:
00899
00900
if (((op &
JF_JOURNAL_OP_DO) && !forward) ||
00901 (!(op &
JF_JOURNAL_OP_DO) && forward))
00902
THROW(INVALID_REDO_UNDO_FLAG1);
00903
break;
00904
case JF_JOURNAL_OP_CODE_SYNC:
00905
THROW(NONE);
00906
default:
00907
THROW(INVALID_OPERATOR_CODE1);
00908 }
00909
00910
00911
if (!forward && ctrl_code ==
JF_JOURNAL_OP_CODE_UPDATE) {
00912
00913
if (size > jr->
undo_data_alloc) {
00914
if (NULL == (tmp_data = realloc(jr->
undo_data,
00915 size)))
00916
THROW(REALLOC_ERROR1);
00917 jr->
undo_data = tmp_data;
00918 jr->
undo_data_alloc = size;
00919 }
00920 }
else {
00921
if (size > jr->
redo_data_alloc) {
00922
if (NULL == (tmp_data = realloc(jr->
redo_data,
00923 size)))
00924
THROW(REALLOC_ERROR2);
00925 jr->
redo_data = tmp_data;
00926 jr->
redo_data_alloc = size;
00927 }
00928 }
00929
00930
00931
if (!forward &&
00932 0 !=
fseeko(
00933 jrn_stream,
00934 -((
jf_offset_t)(
sizeof(ctrl_code)) +
00935 (
jf_offset_t)size), SEEK_CUR))
00936
THROW(FSEEK_ERROR2);
00937
00938
00939
if (forward &&
00940 (ctrl_code ==
JF_JOURNAL_OP_CODE_UPDATE ||
00941 ctrl_code ==
JF_JOURNAL_OP_CODE_APPEND)) {
00942
if (1 != fread(&(jr->
offset),
sizeof(jr->
offset), 1,
00943 jrn_stream))
00944
THROW(FREAD_ERROR2);
00945 }
00946
00947
00948 tmp_data = (!forward && ctrl_code ==
00949
JF_JOURNAL_OP_CODE_UPDATE) ?
00950 jr->
undo_data : jr->
redo_data;
00951
if (1 != fread(tmp_data, size, 1, jrn_stream))
00952
THROW(FREAD_ERROR3);
00953
00954
00955
if (ctrl_code ==
JF_JOURNAL_OP_CODE_UPDATE) {
00956
00957
if (forward) {
00958
if (size > jr->
undo_data_alloc) {
00959
if (NULL == (tmp_data = realloc(
00960 jr->
undo_data,
00961 size)))
00962
THROW(REALLOC_ERROR3);
00963 jr->
undo_data = tmp_data;
00964 jr->
undo_data_alloc = size;
00965 }
00966 }
else {
00967
if (size > jr->
redo_data_alloc) {
00968
if (NULL == (tmp_data = realloc(
00969 jr->
redo_data,
00970 size)))
00971
THROW(REALLOC_ERROR4);
00972 jr->
redo_data = tmp_data;
00973 jr->
redo_data_alloc = size;
00974 }
00975 }
00976
00977
00978
if (!forward &&
00979 0 !=
fseeko(
00980 jrn_stream, -((
jf_offset_t)(size * 2)),
00981 SEEK_CUR))
00982
THROW(FSEEK_ERROR3);
00983
00984
00985 tmp_data = forward ? jr->
undo_data : jr->
redo_data;
00986
if (1 != fread(tmp_data, size, 1, jrn_stream))
00987
THROW(FREAD_ERROR4);
00988 }
00989
00990
00991
if (!forward &&
00992 0 !=
fseeko(
00993 jrn_stream, -((
jf_offset_t)size), SEEK_CUR))
00994
THROW(FSEEK_ERROR4);
00995
00996
00997
if (!forward &&
00998 (ctrl_code ==
JF_JOURNAL_OP_CODE_UPDATE ||
00999 ctrl_code ==
JF_JOURNAL_OP_CODE_APPEND)) {
01000
if (0 !=
fseeko(jrn_stream,
01001 -((
jf_offset_t)
sizeof(
jf_offset_t)),
01002 SEEK_CUR))
01003
THROW(FSEEK_ERROR5);
01004
if (1 != fread(&(jr->
offset),
sizeof(jr->
offset), 1,
01005 jrn_stream))
01006
THROW(FREAD_ERROR5);
01007
if (0 !=
fseeko(jrn_stream,
01008 -((
jf_offset_t)
sizeof(
jf_offset_t)),
01009 SEEK_CUR))
01010
THROW(FSEEK_ERROR6);
01011 }
01012
01013
01014
if (!forward &&
01015 0 !=
fseeko(
01016 jrn_stream, -((
jf_offset_t)
sizeof(ctrl_code)),
01017 SEEK_CUR))
01018
THROW(FSEEK_ERROR7);
01019
01020
01021
if (1 != fread(&ctrl_code,
sizeof(ctrl_code), 1, jrn_stream))
01022
THROW(FREAD_ERROR6);
01023
if (forward)
01024 jr->
undo_code = ctrl_code;
01025
else
01026 jr->
redo_code = ctrl_code;
01027
01028
01029
if (!forward &&
01030 0 !=
fseeko(
01031 jrn_stream, -((
jf_offset_t)
sizeof(ctrl_code)),
01032 SEEK_CUR))
01033
THROW(FSEEK_ERROR8);
01034
01035
01036 op = ctrl_code &
JF_JOURNAL_OP_MASK;
01037 size = (ctrl_code & journal->
size_mask) >>
01038 journal->
size_mask_shift;
01039
01040
01041
if (((op &
JF_JOURNAL_OP_DO) && forward) ||
01042 (!(op &
JF_JOURNAL_OP_DO) && !forward))
01043
THROW(INVALID_REDO_UNDO_FLAG2);
01044
01045
01046
if ((jr->
undo_code &
JF_JOURNAL_OP_CODE_MASK) !=
01047 (jr->
redo_code &
JF_JOURNAL_OP_CODE_MASK))
01048
THROW(INVALID_OPERATOR_CODE2);
01049
01050
JF_TRACE((
"jf_journal_fetch_record: "
01051
"undo_code = %X, redo_code = %X, "
01052
"offset = " JF_OFFSET_T_FORMAT ", "
01053
"undo_data_alloc = " JF_WORD_T_FORMAT ", "
01054
"redo_data_alloc = " JF_WORD_T_FORMAT "\n",
01055 jr->
undo_code, jr->
redo_code, jr->
offset,
01056 jr->
undo_data_alloc, jr->
redo_data_alloc));
01057
01058
THROW(NONE);
01059 }
CATCH {
01060
switch (excp) {
01061
case EOF_REACHED1:
01062
case EOF_REACHED2:
01063
case EOF_REACHED3:
01064 ret_cod =
JF_RC_EOF;
01065
break;
01066
case FSEEK_ERROR1:
01067
case FSEEK_ERROR2:
01068
case FSEEK_ERROR3:
01069
case FSEEK_ERROR4:
01070
case FSEEK_ERROR5:
01071
case FSEEK_ERROR6:
01072
case FSEEK_ERROR7:
01073
case FSEEK_ERROR8:
01074 ret_cod =
JF_RC_FSEEK_ERROR;
01075
break;
01076
case FTELL_ERROR1:
01077 ret_cod =
JF_RC_FTELL_ERROR;
01078
break;
01079
case FREAD_ERROR1:
01080
case FREAD_ERROR2:
01081
case FREAD_ERROR3:
01082
case FREAD_ERROR4:
01083
case FREAD_ERROR5:
01084
case FREAD_ERROR6:
01085 ret_cod =
JF_RC_FREAD_ERROR;
01086
break;
01087
case REALLOC_ERROR1:
01088
case REALLOC_ERROR2:
01089
case REALLOC_ERROR3:
01090
case REALLOC_ERROR4:
01091 ret_cod =
JF_RC_REALLOC_ERROR;
01092
break;
01093
case INVALID_REDO_UNDO_FLAG1:
01094
case INVALID_REDO_UNDO_FLAG2:
01095
case INVALID_OPERATOR_CODE1:
01096
case INVALID_OPERATOR_CODE2:
01097 ret_cod =
JF_RC_INVALID_CTRL_CODE;
01098
break;
01099
case INVALID_STREAM_POSITION:
01100 ret_cod =
JF_RC_INVALID_STREAM_POSITION;
01101
break;
01102
case NONE:
01103 ret_cod =
JF_RC_OK;
01104
break;
01105
default:
01106 ret_cod =
JF_RC_INTERNAL_ERROR;
01107 }
01108 }
01109
JF_TRACE((
"jf_journal_fetch_record/excp=%d/ret_cod=%d/"
01110
"errno=%d\n", excp, ret_cod, errno));
01111
return ret_cod;
01112 }
01113
01114
01115
01116 int jf_journal_apply_changes(
const jf_journal_t *journal,
01117
const struct jf_journal_record_s *jr)
01118 {
01119
enum Exception { INVALID_OPER
01120 , INVALID_FILE_ID
01121 , INVALID_STREAM
01122 , FSEEK_ERROR
01123 , FWRITE_ERROR
01124 , SET_LAST_UC_SIZE
01125 , NONE } excp;
01126
int ret_cod =
JF_RC_INTERNAL_ERROR;
01127
01128
JF_TRACE((
"jf_journal_apply_changes\n"));
01129 TRY {
01130
jf_word_t oper = jr->
redo_code &
JF_JOURNAL_OP_CODE_MASK;
01131
jf_journal_file_t *jfile;
01132 FILE *stream;
01133
jf_word_t file_id = (jr->
redo_code & journal->
file_id_mask) >>
01134 journal->
file_id_mask_shift;
01135
jf_word_t nof =
jf_journal_file_tab_get_number_of_files(
01136 &(journal->
file_table));
01137
01138
if (oper !=
JF_JOURNAL_OP_CODE_APPEND &&
01139 oper !=
JF_JOURNAL_OP_CODE_UPDATE)
01140
THROW(INVALID_OPER);
01141
01142
01143
if (file_id ==
JF_JOURNAL_JOURNAL_FILE_ID || file_id >= nof)
01144
THROW(INVALID_FILE_ID);
01145
01146
01147 jfile =
jf_journal_file_tab_get_jfile(
01148 &(journal->
file_table), file_id);
01149 stream =
jf_journal_file_get_stream(jfile);
01150
01151
01152
if (
jf_journal_file_get_status(jfile) &
01153
JF_JOURNAL_FILE_ST_OPEN) {
01154
jf_word_t size = (jr->
redo_code &
01155 journal->
size_mask) >>
01156 journal->
size_mask_shift;
01157
jf_offset_t offset = jr->
offset + (
jf_offset_t)size;
01158
if (stream == NULL)
01159
THROW(INVALID_STREAM);
01160
if (0 !=
fseeko(stream, jr->
offset, SEEK_SET))
01161
THROW(FSEEK_ERROR);
01162
if (1 != fwrite(jr->
redo_data, size, 1, stream))
01163
THROW(FWRITE_ERROR);
01164
if (offset >
jf_journal_file_get_last_uc_size(jfile)) {
01165 ret_cod =
jf_journal_file_set_last_uc_size(
01166 jfile, offset);
01167
if (
JF_RC_OK != ret_cod)
01168
THROW(SET_LAST_UC_SIZE);
01169 }
01170 }
01171
01172
THROW(NONE);
01173 }
CATCH {
01174
switch (excp) {
01175
case INVALID_OPER:
01176
case INVALID_FILE_ID:
01177 ret_cod =
JF_RC_INVALID_CTRL_CODE;
01178
break;
01179
case INVALID_STREAM:
01180 ret_cod =
JF_RC_INVALID_STATUS;
01181
break;
01182
case FSEEK_ERROR:
01183 ret_cod =
JF_RC_FSEEK_ERROR;
01184
break;
01185
case FWRITE_ERROR:
01186 ret_cod =
JF_RC_FWRITE_ERROR;
01187
break;
01188
case SET_LAST_UC_SIZE:
01189
break;
01190
case NONE:
01191 ret_cod =
JF_RC_OK;
01192
break;
01193
default:
01194 ret_cod =
JF_RC_INTERNAL_ERROR;
01195 }
01196 }
01197
JF_TRACE((
"jf_journal_apply_changes/excp=%d/ret_cod=%d/"
01198
"errno=%d\n", excp, ret_cod, errno));
01199
return ret_cod;
01200 }
01201
01202
01203
01204 int jf_journal_remove_changes(
const jf_journal_t *journal,
01205
const struct jf_journal_record_s *jr)
01206 {
01207
enum Exception { INVALID_OPER
01208 , INVALID_FILE_ID
01209 , INVALID_STREAM
01210 , FSEEK_ERROR
01211 , FWRITE_ERROR
01212 , NONE } excp;
01213
int ret_cod =
JF_RC_INTERNAL_ERROR;
01214
01215
JF_TRACE((
"jf_journal_remove_changes\n"));
01216 TRY {
01217
jf_word_t oper = jr->
undo_code &
JF_JOURNAL_OP_CODE_MASK;
01218
const jf_journal_file_t *jfile;
01219 FILE *stream;
01220
jf_word_t file_id = (jr->
undo_code & journal->
file_id_mask) >>
01221 journal->
file_id_mask_shift;
01222
jf_word_t nof =
jf_journal_file_tab_get_number_of_files(
01223 &(journal->
file_table));
01224
01225
if (oper !=
JF_JOURNAL_OP_CODE_APPEND &&
01226 oper !=
JF_JOURNAL_OP_CODE_UPDATE)
01227
THROW(INVALID_OPER);
01228
01229
01230
if (file_id ==
JF_JOURNAL_JOURNAL_FILE_ID || file_id >= nof)
01231
THROW(INVALID_FILE_ID);
01232
01233
01234 jfile =
jf_journal_file_tab_get_jfile(
01235 &(journal->
file_table), file_id);
01236 stream =
jf_journal_file_get_stream(jfile);
01237
01238
JF_TRACE((
"jf_journal_remove_changes: file_id = "
01239
JF_WORD_T_FORMAT ", file_status = "JF_WORD_T_FORMAT
01240
"\n", file_id,
jf_journal_file_get_status(jfile)));
01241
01242
01243
if ((
jf_journal_file_get_status(jfile) &
01244
JF_JOURNAL_FILE_ST_OPEN) &&
01245 !(
jf_journal_file_get_status(jfile) &
01246
JF_JOURNAL_FILE_ST_SYNC)) {
01247
jf_word_t size =
01248 (jr->
undo_code & journal->
size_mask) >>
01249 journal->
size_mask_shift;
01250
JF_TRACE((
"jf_journal_remove_changes: file_id "
01251
"= %u, offset = " JF_OFFSET_T_FORMAT ", "
01252
"size = " JF_WORD_T_FORMAT "\n",
01253 file_id, jr->
offset, size));
01254
if (stream == NULL)
01255
THROW(INVALID_STREAM);
01256
if (0 !=
fseeko(stream, jr->
offset, SEEK_SET))
01257
THROW(FSEEK_ERROR);
01258
if (oper ==
JF_JOURNAL_OP_CODE_UPDATE &&
01259 1 != fwrite(jr->
undo_data, size, 1, stream))
01260
THROW(FWRITE_ERROR);
01261 }
01262
JF_CRASH_SIMUL((
JF_CRASH_SIMUL_F_REMOVE_CHANGES_1));
01263
01264
THROW(NONE);
01265 }
CATCH {
01266
switch (excp) {
01267
case INVALID_OPER:
01268
case INVALID_FILE_ID:
01269 ret_cod =
JF_RC_INVALID_CTRL_CODE;
01270
break;
01271
case INVALID_STREAM:
01272 ret_cod =
JF_RC_INVALID_STATUS;
01273
break;
01274
case FSEEK_ERROR:
01275 ret_cod =
JF_RC_FSEEK_ERROR;
01276
break;
01277
case FWRITE_ERROR:
01278 ret_cod =
JF_RC_FWRITE_ERROR;
01279
break;
01280
case NONE:
01281 ret_cod =
JF_RC_OK;
01282
break;
01283
default:
01284 ret_cod =
JF_RC_INTERNAL_ERROR;
01285 }
01286 }
01287
JF_TRACE((
"jf_journal_remove_changes/excp=%d/ret_cod=%d/"
01288
"errno=%d\n", excp, ret_cod, errno));
01289
return ret_cod;
01290 }
01291
01292
01293
01294 const char *
jf_journal_describe_code(
const jf_word_t ctrl_code)
01295 {
01296
switch (ctrl_code &
JF_JOURNAL_OP_MASK) {
01297
case JF_JOURNAL_OP_CODE_APPEND |
JF_JOURNAL_OP_DO:
01298
return "REDO APPEND";
01299
case JF_JOURNAL_OP_CODE_APPEND:
01300
return "UNDO APPEND";
01301
case JF_JOURNAL_OP_CODE_UPDATE |
JF_JOURNAL_OP_DO:
01302
return "REDO UPDATE";
01303
case JF_JOURNAL_OP_CODE_UPDATE:
01304
return "UNDO UPDATE";
01305
case JF_JOURNAL_OP_CODE_SYNC |
JF_JOURNAL_OP_DO:
01306
return "COMMIT";
01307
case JF_JOURNAL_OP_CODE_SYNC:
01308
return "ROLLBACK";
01309
default:
01310
return "UNKNOWN CODE";
01311 }
01312 }
01313
01314
01315
01316 int jf_journal_trace_record(
const jf_journal_t *journal,
01317
const struct jf_journal_record_s *jr,
01318
jf_offset_t record_offset, FILE *out_stream,
01319 uint32_t flags)
01320 {
01321
enum Exception { INVALID_OPERATOR_CODE
01322 , NONE } excp;
01323
int ret_cod =
JF_RC_INTERNAL_ERROR;
01324
01325
JF_TRACE((
"jf_journal_trace_record\n"));
01326 TRY {
01327
jf_word_t size, file_id, op;
01328
01329 op = jr->
redo_code &
JF_JOURNAL_OP_MASK;
01330 file_id = (jr->
redo_code & journal->
file_id_mask) >>
01331 journal->
file_id_mask_shift;
01332 size = (jr->
redo_code & journal->
size_mask) >>
01333 journal->
size_mask_shift;
01334
01335
switch (op &
JF_JOURNAL_OP_CODE_MASK) {
01336
case JF_JOURNAL_OP_CODE_APPEND:
01337 fprintf(out_stream,
" <append "
01338
"jrn_rec_off='" JF_OFFSET_T_FORMAT "' "
01339
"file_id='" JF_WORD_T_FORMAT "' "
01340
"size='" JF_WORD_T_FORMAT "' "
01341
"offset='" JF_OFFSET_T_FORMAT "'>\n",
01342 record_offset, file_id, size, jr->
offset);
01343
if (flags &
JF_JOURNAL_ANALYZE_TRACE_HEX_DATA) {
01344 fprintf(out_stream,
" <data type='redo' "
01345
"format='hex'>");
01346
jf_trace_hex_data(jr->
redo_data, size,
01347 out_stream);
01348 fprintf(out_stream,
"</data>\n");
01349 }
01350
if (flags &
JF_JOURNAL_ANALYZE_TRACE_TEXT_DATA) {
01351 fprintf(out_stream,
01352
" <data type='redo' "
01353
"format='text'>");
01354
jf_trace_text_data(jr->
redo_data, size,
01355 out_stream);
01356 fprintf(out_stream,
"</data>\n");
01357 }
01358 fprintf(out_stream,
" </append>\n");
01359
break;
01360
case JF_JOURNAL_OP_CODE_UPDATE:
01361 fprintf(out_stream,
" <update "
01362
"jrn_rec_off='" JF_OFFSET_T_FORMAT "' "
01363
"file_id='" JF_WORD_T_FORMAT "' "
01364
"size='" JF_WORD_T_FORMAT "' "
01365
"offset='" JF_OFFSET_T_FORMAT "'>\n",
01366 record_offset, file_id, size, jr->
offset);
01367
if (flags &
JF_JOURNAL_ANALYZE_TRACE_HEX_DATA) {
01368 fprintf(out_stream,
" <data type='redo' "
01369
"format='hex'>");
01370
jf_trace_hex_data(jr->
redo_data, size,
01371 out_stream);
01372 fprintf(out_stream,
"</data>\n");
01373 }
01374
if (flags &
JF_JOURNAL_ANALYZE_TRACE_TEXT_DATA) {
01375 fprintf(out_stream,
01376
" <data type='redo' "
01377
"format='text'>");
01378
jf_trace_text_data(jr->
redo_data, size,
01379 out_stream);
01380 fprintf(out_stream,
"</data>\n");
01381 }
01382
if (flags &
JF_JOURNAL_ANALYZE_TRACE_HEX_DATA) {
01383 fprintf(out_stream,
" <data type='undo' "
01384
"format='hex'>");
01385
jf_trace_hex_data(jr->
undo_data, size,
01386 out_stream);
01387 fprintf(out_stream,
"</data>\n");
01388 }
01389
if (flags &
JF_JOURNAL_ANALYZE_TRACE_TEXT_DATA) {
01390 fprintf(out_stream,
01391
" <data type='undo' "
01392
"format='text'>");
01393
jf_trace_text_data(jr->
undo_data, size,
01394 out_stream);
01395 fprintf(out_stream,
"</data>\n");
01396 }
01397 fprintf(out_stream,
" </update>\n");
01398
break;
01399
case JF_JOURNAL_OP_CODE_SYNC:
01400 fprintf(out_stream,
01401
" <%s "
01402
"jrn_rec_off='" JF_OFFSET_T_FORMAT "' "
01403
"file_id='" JF_WORD_T_FORMAT "'/>\n",
01404 (op &
JF_JOURNAL_OP_DO) ?
01405
"commit" :
"rollback", record_offset, file_id);
01406
break;
01407
default:
01408
THROW(INVALID_OPERATOR_CODE);
01409 }
01410
01411
THROW(NONE);
01412 }
CATCH {
01413
switch (excp) {
01414
case INVALID_OPERATOR_CODE:
01415 ret_cod =
JF_RC_INVALID_CTRL_CODE;
01416
break;
01417
case NONE:
01418 ret_cod =
JF_RC_OK;
01419
break;
01420
default:
01421 ret_cod =
JF_RC_INTERNAL_ERROR;
01422 }
01423 }
01424
JF_TRACE((
"jf_journal_trace_record/excp=%d/ret_cod=%d/"
01425
"errno=%d\n", excp, ret_cod, errno));
01426
return ret_cod;
01427 }
01428