persist.cc (fstransform-0.9.3-src) | : | persist.cc (fstransform-0.9.4) | ||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
FT_IO_NAMESPACE_BEGIN | FT_IO_NAMESPACE_BEGIN | |||
/** constructor */ | /** constructor */ | |||
fr_persist::fr_persist(fr_job & job) | fr_persist::fr_persist(fr_job & job) | |||
: this_progress1((ft_ull)-1), this_progress2((ft_ull)-1), | : this_progress1((ft_ull)-1), this_progress2((ft_ull)-1), | |||
this_persist_path(), this_persist_file(NULL), | this_persist_path(), this_persist_file(NULL), | |||
this_job(job), this_replaying(false) | this_job(job), this_replaying(false) | |||
{ } | { } | |||
#define FC_PERSIST_FILE_VERSION "version 0.9.4" | ||||
#define FC_PERSIST_HEADER_SIMULATED "simulated job, " FC_PERSIST_FILE_VERSION | ||||
#define FC_PERSIST_HEADER_REAL "real job, " FC_PERSIST_FILE_VERSION | ||||
#define FC_OLD_HEADER_SIMULATED "simulated job" | ||||
#define FC_OLD_HEADER_REAL "real job" | ||||
/** create and open persistence file job.job_dir() + "/fsremap.persist" */ | /** create and open persistence file job.job_dir() + "/fsremap.persist" */ | |||
int fr_persist::open() | int fr_persist::open() | |||
{ | { | |||
if (this_persist_file != NULL) { | if (this_persist_file != NULL) { | |||
ff_log(FC_ERROR, 0, "unexpected call to open(), persistence is already i nitialized"); | ff_log(FC_ERROR, 0, "unexpected call to open(), persistence is already i nitialized"); | |||
// return error as already reported | // return error as already reported | |||
return -EISCONN; | return -EISCONN; | |||
} | } | |||
this_persist_path = this_job.job_dir(); | this_persist_path = this_job.job_dir(); | |||
skipping to change at line 76 | skipping to change at line 84 | |||
// fopen(... "a+") = Open for reading and appending. The file is created if it does not exist. | // fopen(... "a+") = Open for reading and appending. The file is created if it does not exist. | |||
// The initial file position for reading is at the beginning of the file, | // The initial file position for reading is at the beginning of the file, | |||
// but output is always appended to the end of the file | // but output is always appended to the end of the file | |||
if ((this_persist_file = fopen(persist_path, "a+")) == NULL) | if ((this_persist_file = fopen(persist_path, "a+")) == NULL) | |||
return ff_log(FC_ERROR, errno, "failed to open persistence file '%s'", p ersist_path); | return ff_log(FC_ERROR, errno, "failed to open persistence file '%s'", p ersist_path); | |||
this_replaying = this_job.resuming_job(); | this_replaying = this_job.resuming_job(); | |||
const bool simulated = this_job.simulate_run(); | const bool simulated = this_job.simulate_run(); | |||
const char * header = simulated ? "simulated job" : "real job"; | const char * header = simulated ? FC_PERSIST_HEADER_SIMULATED : FC_PERSIST_H | |||
const char * other_header = simulated ? "real job" : "simulated job"; | EADER_REAL; | |||
const char * other_header = simulated ? FC_PERSIST_HEADER_REAL : FC_PERSIST_ | ||||
HEADER_SIMULATED; | ||||
const char * header_old = simulated ? FC_OLD_HEADER_SIMULATED : FC_OLD_HEADE | ||||
R_REAL; | ||||
const char * other_header_old = simulated ? FC_OLD_HEADER_REAL : FC_OLD_HEAD | ||||
ER_SIMULATED; | ||||
int err = 0; | int err = 0; | |||
if (this_replaying) { | if (this_replaying) { | |||
enum { FT_LINE_LEN = 80 }; | enum { FT_LINE_LEN = 80 }; | |||
char line[FT_LINE_LEN + 1] = { '\0' }; | char line[FT_LINE_LEN + 1] = { '\0' }; | |||
if (fgets(line, FT_LINE_LEN, this_persist_file) == NULL) | if (fgets(line, FT_LINE_LEN, this_persist_file) == NULL) | |||
err = ff_log(FC_ERROR, errno, "I/O error reading from persistence fi le '%s'", this_persist_path.c_str()); | err = ff_log(FC_ERROR, errno, "I/O error reading from persistence fi le '%s'", this_persist_path.c_str()); | |||
else { | else { | |||
// paranoia | // paranoia | |||
line[FT_LINE_LEN] = '\0'; | line[FT_LINE_LEN] = '\0'; | |||
ft_size line_len = strlen(line); | ft_size line_len = strlen(line); | |||
// remove final '\n' if present | // remove final '\n' if present | |||
if (line_len && line[line_len - 1] == '\n') | if (line_len && line[line_len - 1] == '\n') | |||
line[--line_len] = '\0'; | line[--line_len] = '\0'; | |||
if (!strcmp(header, line)) { | if (!strcmp(header, line) || !strcmp(header_old, line)) { | |||
err = do_read(this_progress1, this_progress2); | err = do_read(this_progress1, this_progress2); | |||
} else if (!strcmp(other_header, line)) { | ||||
} else if (!strcmp(other_header, line) || !strcmp(other_header_old, | ||||
line)) { | ||||
ff_log(FC_ERROR, 0, "tried to resume a %s: you MUST%s specify op tion '-n'%s", | ff_log(FC_ERROR, 0, "tried to resume a %s: you MUST%s specify op tion '-n'%s", | |||
other_header, simulated ? " NOT" : "", simulated ? "" : " to simulate again"); | other_header, simulated ? " NOT" : "", simulated ? "" : " to simulate again"); | |||
err = -EINVAL; | err = -EINVAL; | |||
} else { | } else { | |||
ff_log(FC_ERROR, 0, "corrupted persistence file '%s': expected h eader '%s', found '%s'", | ff_log(FC_ERROR, 0, "unsupported or corrupted persistence file ' %s': expected header '%s', found '%s'", | |||
persist_path, header, line); | persist_path, header, line); | |||
err = -EINVAL; | err = -EINVAL; | |||
} | } | |||
} | } | |||
} else { | } else { | |||
if (fprintf(this_persist_file, "%s\n", header) < 0) | if (fprintf(this_persist_file, "%s\n", header) < 0) | |||
err = ff_log(FC_ERROR, errno, "I/O error writing to persistence file '%s'", this_persist_path.c_str()); | err = ff_log(FC_ERROR, errno, "I/O error writing to persistence file '%s'", this_persist_path.c_str()); | |||
else | else | |||
err = do_flush(); | err = do_flush(); | |||
} | } | |||
skipping to change at line 139 | skipping to change at line 152 | |||
// compare job_{primary,secondary}_size with the ones in persistence (if pre sent) | // compare job_{primary,secondary}_size with the ones in persistence (if pre sent) | |||
ft_ull persist_size1 = 0, persist_size2 = 0; | ft_ull persist_size1 = 0, persist_size2 = 0; | |||
int err = read(persist_size1, persist_size2); | int err = read(persist_size1, persist_size2); | |||
if (err != 0) | if (err != 0) | |||
return err; | return err; | |||
if (persist_size1 != 0 && job_size1 != 0 | if (persist_size1 != 0 && job_size1 != 0 | |||
&& persist_size1 != (ft_ull) job_size1) | && persist_size1 != (ft_ull) job_size1) | |||
{ | { | |||
ff_log(FC_ERROR, 0, "mismatched primary storage exact size: %"FT_ULL" by tes requested from command line, %"FT_ULL | ff_log(FC_ERROR, 0, "mismatched primary storage exact size: %" FT_ULL " bytes requested from command line, %" FT_ULL | |||
" bytes found in persistence file", (ft_ull) job_size1, persist_s ize1); | " bytes found in persistence file", (ft_ull) job_size1, persist_s ize1); | |||
err = -EINVAL; | err = -EINVAL; | |||
} | } | |||
if (persist_size2 != 0 && job_size2 != 0 | if (persist_size2 != 0 && job_size2 != 0 | |||
&& persist_size2 != (ft_ull) job_size2) | && persist_size2 != (ft_ull) job_size2) | |||
{ | { | |||
ff_log(FC_ERROR, 0, "mismatched secondary storage exact size: %"FT_ULL" bytes requested from command line, %"FT_ULL | ff_log(FC_ERROR, 0, "mismatched secondary storage exact size: %" FT_ULL " bytes requested from command line, %" FT_ULL | |||
" bytes found in persistence file", (ft_ull) job_size2, persist_s ize2); | " bytes found in persistence file", (ft_ull) job_size2, persist_s ize2); | |||
err = -EINVAL; | err = -EINVAL; | |||
} | } | |||
if (err != 0) | if (err != 0) | |||
return err; | return err; | |||
// reuse persisted primary/secondary exact size. | // reuse persisted primary/secondary exact size. | |||
// ABSOLUTELY needed to reproduce the same operations while replaying | // ABSOLUTELY needed to reproduce the same operations while replaying | |||
size1 = (ft_size) persist_size1; | size1 = (ft_size) persist_size1; | |||
size2 = (ft_size) persist_size2; | size2 = (ft_size) persist_size2; | |||
skipping to change at line 184 | skipping to change at line 197 | |||
progress1 = this_progress1; | progress1 = this_progress1; | |||
progress2 = this_progress2; | progress2 = this_progress2; | |||
return do_read(this_progress1, this_progress2); | return do_read(this_progress1, this_progress2); | |||
} | } | |||
/** read or write a step in persistence fle */ | /** read or write a step in persistence fle */ | |||
int fr_persist::next(ft_ull progress1, ft_ull progress2) | int fr_persist::next(ft_ull progress1, ft_ull progress2) | |||
{ | { | |||
ff_log(FC_DEBUG, 0, "blocks left: device = %"FT_ULL", storage = %"FT_ULL", r eplaying = %s", | ff_log(FC_DEBUG, 0, "blocks left: device = %" FT_ULL ", storage = %" FT_ULL ", replaying = %s", | |||
progress1, progress2, this_replaying ? "true" : "false"); | progress1, progress2, this_replaying ? "true" : "false"); | |||
if (!this_replaying) | if (!this_replaying) | |||
return do_write(progress1, progress2); | return do_write(progress1, progress2); | |||
if (progress1 != this_progress1 || progress2 != this_progress2) { | if (progress1 != this_progress1 || progress2 != this_progress2) { | |||
ff_log(FC_ERROR, 0, "unexpected values found while replaying persistence file '%s'", | ff_log(FC_ERROR, 0, "unexpected values found while replaying persistence file '%s'", | |||
this_persist_path.c_str()); | this_persist_path.c_str()); | |||
ff_log(FC_ERROR, 0, "\texpected %"FT_ULL" %"FT_ULL", found %"FT_ULL" %"F T_ULL"\n", | ff_log(FC_ERROR, 0, "\texpected %" FT_ULL " %" FT_ULL ", found %" FT_ULL " %" FT_ULL "\n", | |||
progress1, progress2, this_progress1, this_progress2); | progress1, progress2, this_progress1, this_progress2); | |||
return -EINVAL; | return -EINVAL; | |||
} | } | |||
return do_read(this_progress1, this_progress2); | return do_read(this_progress1, this_progress2); | |||
} | } | |||
/** try to read data from persistence fle */ | /** try to read data from persistence fle */ | |||
int fr_persist::do_read(ft_ull & progress1, ft_ull & progress2) | int fr_persist::do_read(ft_ull & progress1, ft_ull & progress2) | |||
{ | { | |||
int err = 0; | int err = 0; | |||
if (this_replaying) { | if (this_replaying) { | |||
int items = fscanf(this_persist_file, "%"FT_ULL"\t%"FT_ULL"\n", & progre ss1, & progress2); | int items = fscanf(this_persist_file, "%" FT_ULL "\t%" FT_ULL "\n", & pr ogress1, & progress2); | |||
if (items == 2) { | if (items == 2) { | |||
/* ok */ | /* ok */ | |||
} else if (feof(this_persist_file)) { | } else if (feof(this_persist_file)) { | |||
this_replaying = false; | this_replaying = false; | |||
} else { | } else { | |||
ff_log(FC_ERROR, 0, "corrupted persistence file '%s'! expecting two numeric values, found %d", | ff_log(FC_ERROR, 0, "corrupted persistence file '%s'! expecting two numeric values, found %d", | |||
this_persist_path.c_str(), (int) items); | this_persist_path.c_str(), (int) items); | |||
err = -EFAULT; | err = -EFAULT; | |||
} | } | |||
} | } | |||
return err; | return err; | |||
} | } | |||
/** try to write data into persistence fle */ | /** try to write data into persistence fle */ | |||
int fr_persist::do_write(ft_ull progress1, ft_ull progress2) | int fr_persist::do_write(ft_ull progress1, ft_ull progress2) | |||
{ | { | |||
if (fprintf(this_persist_file, "%"FT_ULL"\t%"FT_ULL"\n", progress1, progress 2) <= 0) | if (fprintf(this_persist_file, "%" FT_ULL "\t%" FT_ULL "\n", progress1, prog ress2) <= 0) | |||
return ff_log(FC_ERROR, errno, "I/O error writing to persistence file '% s'", this_persist_path.c_str()); | return ff_log(FC_ERROR, errno, "I/O error writing to persistence file '% s'", this_persist_path.c_str()); | |||
return do_flush(); | return do_flush(); | |||
} | } | |||
/** flush this_persist_file to disk: calls fflush() then fdatasync() or fsync() */ | /** flush this_persist_file to disk: calls fflush() then fdatasync() or fsync() */ | |||
int fr_persist::do_flush() | int fr_persist::do_flush() | |||
{ | { | |||
if (fflush(this_persist_file) == 0) { | if (fflush(this_persist_file) == 0) { | |||
int fd = fileno(this_persist_file); | int fd = fileno(this_persist_file); | |||
End of changes. 11 change blocks. | ||||
11 lines changed or deleted | 29 lines changed or added |