Commit 28d927af authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

More logformatting stuff. Addresses #11

git-svn-id: file:///svn/tokudb@710 c7de825b-a66e-492c-adef-691d508d4ae1
parent 12fd5638
......@@ -8,6 +8,7 @@
*/
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
typedef struct field {
char *type;
......@@ -47,66 +48,147 @@ const struct logtype logtypes[] = {
body; \
} })
void generate_log_struct(void) {
FILE *f = fopen("log_struct.h", "w");
assert(f!=0);
void fprintf2 (FILE *f1, FILE *f2, const char *format, ...) {
va_list ap;
int r;
va_start(ap, format);
r=vfprintf(f1, format, ap); assert(r>=0);
r=vfprintf(f2, format, ap); assert(r>=0);
va_end(ap);
}
FILE *hf=0, *cf=0;
void generate_lt_enum (void) {
int count=0;
fprintf(hf, "enum lt_command {");
DO_LOGTYPES(lt,
({ fprintf(f, "struct logtype_%s {\n", lt->name);
fprintf(f, " %-16s lsn;\n", "LSN");
({
if (count!=0) fprintf(hf, ",");
count++;
fprintf(hf, "\n");
fprintf(hf," LT_%-16s = '%c'", lt->name, lt->command);
}));
fprintf(hf, "\n};\n\n");
}
void generate_log_struct (void) {
DO_LOGTYPES(lt,
({ fprintf(hf, "struct logtype_%s {\n", lt->name);
fprintf(hf, " %-16s lsn;\n", "LSN");
DO_FIELDS(ft, lt,
fprintf(f, " %-16s %s;\n", ft->type, ft->name));
fprintf(f, " %-16s crc;\n", "u_int_32");
fprintf(f, " %-16s len;\n", "u_int_32");
fprintf(f, "};\n");
fprintf(hf, " %-16s %s;\n", ft->type, ft->name));
fprintf(hf, " %-16s crc;\n", "u_int_32");
fprintf(hf, " %-16s len;\n", "u_int_32");
fprintf(hf, "};\n");
}));
int r=fclose(f);
assert(r==0);
}
void generate_log_writer(void) {
void generate_log_writer (void) {
FILE *f = fopen("log_write.c", "w");
assert(f!=0);
DO_LOGTYPES(lt, ({
fprintf(f, "int toku_log_%s (TOKULOGGE logger, LSN lsn", lt->name);
fprintf2(cf, hf, "int toku_log_%s (TOKULOGGER logger, LSN lsn", lt->name);
DO_FIELDS(ft, lt,
fprintf(f, ", %s %s", ft->type, ft->name));
fprintf(f, ") {\n");
fprintf(f, " const int buflen= (1 // log command\n");
fprintf(f, " +8 // lsn\n");
fprintf2(cf, hf, ", %s %s", ft->type, ft->name));
fprintf(hf, ");\n");
fprintf(cf, ") {\n");
fprintf(cf, " const int buflen= (1 // log command\n");
fprintf(cf, " +8 // lsn\n");
DO_FIELDS(ft, lt,
fprintf(f, " +toku_logsizeof_%s(%s)\n", ft->type, ft->name));
fprintf(f, " +8 // crc + len\n");
fprintf(f, " );\n");
fprintf(f, " struct wbuf wbuf;\n");
fprintf(f, " const char *buf = toku_malloc(buflen);\n");
fprintf(f, " if (buf==0) return errno;\n");
fprintf(f, " wbuf_init(&wbuf, buf, buflen)\n");
fprintf(f, " wbuf_char(&wbuf, '%c');\n", lt->command);
fprintf(f, " wbuf_lsn(&wbuf, lsn);\n");
fprintf(cf, " +toku_logsizeof_%s(%s)\n", ft->type, ft->name));
fprintf(cf, " +8 // crc + len\n");
fprintf(cf, " );\n");
fprintf(cf, " struct wbuf wbuf;\n");
fprintf(cf, " const char *buf = toku_malloc(buflen);\n");
fprintf(cf, " if (buf==0) return errno;\n");
fprintf(cf, " wbuf_init(&wbuf, buf, buflen)\n");
fprintf(cf, " wbuf_char(&wbuf, '%c');\n", lt->command);
fprintf(cf, " wbuf_lsn(&wbuf, lsn);\n");
DO_FIELDS(ft, lt,
fprintf(f, " wbuf_%s(&wbuf, %s);\n", ft->type, ft->name));
fprintf(f, " int r= tokulogger_finish(logger, &wbuf);\n");
fprintf(f, " assert(buf.ndone==buflen);\n");
fprintf(f, " toku_free(buf);\n");
fprintf(cf, " wbuf_%s(&wbuf, %s);\n", ft->type, ft->name));
fprintf(cf, " int r= tokulogger_finish(logger, &wbuf);\n");
fprintf(cf, " assert(buf.ndone==buflen);\n");
fprintf(cf, " toku_free(buf);\n");
if (lt->command=='C') {
fprintf(f, " if (r!=0) return r;\n");
fprintf(f, " // commit has some extra work to do.\n");
fprintf(f, " if (txn->parent) return 0; // don't fsync if there is a parent.\n");
fprintf(f, " else return tokulogger_fsync(logger);\n");
fprintf(cf, " if (r!=0) return r;\n");
fprintf(cf, " // commit has some extra work to do.\n");
fprintf(cf, " if (txn->parent) return 0; // don't fsync if there is a parent.\n");
fprintf(cf, " else return tokulogger_fsync(logger);\n");
} else {
fprintf(f, " return r;\n");
fprintf(cf, " return r;\n");
}
fprintf(f, "}\n\n");
fprintf(cf, "}\n\n");
}));
int r=fclose(f);
assert(r==0);
}
void generate_log_reader (void) {
DO_LOGTYPES(lt, ({
fprintf2(cf, hf, "int tokulog_fread_%s (FILE *infile, struct logtype_%s *data, char cmd)", lt->name, lt->name);
fprintf(hf, ";\n");
fprintf(cf, " {\n");
fprintf(cf, " int r=0, actual_len=1;\n");
fprintf(cf, " u_int32_t crc = toku_crc32(0, &cmd, 1);\n");
fprintf(cf, " r=toku_fread_%-16s(infile, &data->%-16s, &crc, &actual_len); if (r!=0) return r;\n", "LSN", "lsn");
DO_FIELDS(ft, lt,
fprintf(cf, " r=toku_fread_%-16s(infile, &data->%-16s, &crc, &actual_len); if (r!=0) return r;\n", ft->type, ft->name));
fprintf(cf, " u_int32_t crc_in_file, len_in_file;\n");
fprintf(cf, " r=toku_fread_uint32(infile, &crc_in_file); actual_len+=4; if (r!=0) return r;\n");
fprintf(cf, " r=toku_fread_uint32(infile, &len_in_file); actual_len+=4; if (r!=0) return r;\n");
fprintf(cf, " if (crc_in_file!=crc || len_in_file!=actual_len) return DB_BADFORMAT;\n");
fprintf(cf, " return 0;\n");
fprintf(cf, "}\n\n");
}));
}
void generate_logprint (void) {
fprintf(cf, "int logprint(FILE *outf, FILE *f, int n_records_limit) {\n");
fprintf(cf, " int i, cmd, r;\n");
fprintf(cf, " for (i=0; i!=count && (cmd=fgetc(f))!=EOF; i++) {\n");
fprintf(cf, " u_int32_t len_in_file, len=1;\n");
fprintf(cf, " char charcmd = cmd;\n");
fprintf(cf, " u_int32_t crc_in_file, crc = toku_crc32(0, &char_cmd, 1);\n");
fprintf(cf, " switch ((enum lt_command)cmd) {\n");
DO_LOGTYPES(lt, ({
fprintf(cf, " case LT_%s: \n", lt->name);
// We aren't using the log reader here because we want better diagnostics as soon as things go wrong.
fprintf(cf, " r = toku_logprint_LSN(outf, f, &crc, &len); if (r!=0) return r;\n");
DO_FIELDS(ft, lt,
fprintf(cf, " r = toku_logprint_%s(outf, f, &crc, &len); if (r!=0) return r;\n", ft->type));
fprintf(cf, " r = toku_fread_uint32(infile, &crc_in_file); len+=4; if (r!=0) return r;\n");
fprintf(cf, " fprintf(outf, \" crc=%%d\", crc_in_file);\n");
fprintf(cf, " if (crc_in_file!=crc) fprintf(\" actual_crc=%%d\", actual_crc);\n");
fprintf(cf, " r = toku_fread_uint32(infile, &len_in_file); len+=4; if (r!=0) return r;\n");
fprintf(cf, " fprintf(outf, \" len=%%d\", len_in_file);\n");
fprintf(cf, " if (len_in_file!=len) fprintf(\" actual_len=%%d\", actual_len);\n");
fprintf(cf, " if (len_in_file!=len || crc_in_file!=crc) return DB_BADFORMAT;\n");
fprintf(cf, " goto next;\n\n");
}));
fprintf(cf, " }\n");
fprintf(cf, " fprintf(outf, \"Unknown command %%d ('%%c')\", cmd, cmd);\n");
fprintf(cf, " return DB_BADFORMAT;\n");
fprintf(cf, " next: ;\n");
fprintf(cf, " }\n");
fprintf(cf, " return 0;\n");
fprintf(cf, "}\n\n");
}
int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
cf = fopen("log_code.c", "w"); assert(cf!=0);
hf = fopen("log_header.h", "w"); assert(hf!=0);
generate_log_struct();
generate_log_writer();
generate_log_reader();
generate_logprint();
{
int r=fclose(hf);
assert(r==0);
r=fclose(cf);
assert(r==0);
}
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment