📄 gen_rec.awk
字号:
#!/bin/sh -## See the file LICENSE for redistribution information.## Copyright (c) 1996-2004# Sleepycat Software. All rights reserved.## $Id: gen_rec.awk,v 11.110 2004/10/20 20:40:58 bostic Exp $## This awk script generates all the log, print, and read routines for the DB# logging. It also generates a template for the recovery functions (these# functions must still be edited, but are highly stylized and the initial# template gets you a fair way along the path).## For a given file prefix.src, we generate a file prefix_auto.c, and a file# prefix_auto.h that contains:## external declarations for the file's functions# defines for the physical record types# (logical types are defined in each subsystem manually)# structures to contain the data unmarshalled from the log.## This awk script requires that four variables be set when it is called:## source_file -- the C source file being created# header_file -- the C #include file being created# template_file -- the template file being created## And stdin must be the input file that defines the recovery setup.## Within each file prefix.src, we use a number of public keywords (documented# in the reference guide) as well as the following ones which are private to# DB:# DBPRIVATE Indicates that a file will be built as part of DB,# rather than compiled independently, and so can use# DB-private interfaces (such as DB_LOG_NOCOPY).# DB A DB handle. Logs the dbreg fileid for that handle,# and makes the *_log interface take a DB * instead of a# DB_ENV *.# PGDBT Just like DBT, only we know it stores a page or page# header, so we can byte-swap it (once we write the# byte-swapping code, which doesn't exist yet).# LOCKS Just like DBT, but uses a print function for locks.BEGIN { if (source_file == "" || header_file == "" || template_file == "") { print "Usage: gen_rec.awk requires three variables to be set:" print "\theader_file\t-- the recover #include file being created" print "\tprint_file\t-- the print source file being created" print "\tsource_file\t-- the recover source file being created" print "\ttemplate_file\t-- the template file being created" exit } FS="[\t ][\t ]*" CFILE=source_file HFILE=header_file PFILE=print_file TFILE=template_file dbprivate = 0 buf_only = 1;}/^[ ]*DBPRIVATE/ { dbprivate = 1}/^[ ]*PREFIX/ { prefix = $2 num_funcs = 0; # Start .c files. printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \ > CFILE printf("#include \"db_config.h\"\n\n") >> CFILE printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \ > PFILE printf("#include \"db_config.h\"\n\n") >> PFILE if (prefix == "__ham") printf("#ifdef HAVE_HASH\n") >> PFILE if (prefix == "__qam") printf("#ifdef HAVE_QUEUE\n") >> PFILE # Start .h file, make the entire file conditional. printf("/* Do not edit: automatically built by gen_rec.awk. */\n\n") \ > HFILE printf("#ifndef\t%s_AUTO_H\n#define\t%s_AUTO_H\n", prefix, prefix) \ >> HFILE; # Write recovery template file headers # This assumes we're doing DB recovery. printf("#include \"db_config.h\"\n\n") > TFILE printf("#ifndef NO_SYSTEM_INCLUDES\n") >> TFILE printf("#include <sys/types.h>\n\n") >> TFILE printf("#include <string.h>\n") >> TFILE printf("#endif\n\n") >> TFILE printf("#include \"db_int.h\"\n") >> TFILE printf("#include \"dbinc/db_page.h\"\n") >> TFILE printf("#include \"dbinc/%s.h\"\n", prefix) >> TFILE printf("#include \"dbinc/log.h\"\n\n") >> TFILE}/^[ ]*INCLUDE/ { for (i = 2; i < NF; i++) printf("%s ", $i) >> CFILE printf("%s\n", $i) >> CFILE for (i = 2; i < NF; i++) printf("%s ", $i) >> PFILE printf("%s\n", $i) >> PFILE}/^[ ]*(BEGIN|IGNORED|BEGIN_BUF)/ { if (in_begin) { print "Invalid format: missing END statement" exit } in_begin = 1; is_dbt = 0; has_dbp = 0; is_uint = 0; need_log_function = ($1 == "BEGIN") || ($1 == "BEGIN_BUF"); not_buf = ($1 == "BEGIN") || ($1 == "IGNORED"); if (not_buf) buf_only = 0; nvars = 0; thisfunc = $2; funcname = sprintf("%s_%s", prefix, $2); if (not_buf) rectype = $3; funcs[num_funcs] = funcname; ++num_funcs;}/^[ ]*(DB|ARG|DBT|LOCKS|PGDBT|POINTER|TIME)/ { vars[nvars] = $2; types[nvars] = $3; atypes[nvars] = $1; modes[nvars] = $1; formats[nvars] = $NF; for (i = 4; i < NF; i++) types[nvars] = sprintf("%s %s", types[nvars], $i); if ($1 == "DB") { has_dbp = 1; } if ($1 == "DB" || $1 == "ARG" || $1 == "TIME") { sizes[nvars] = sprintf("sizeof(u_int32_t)"); is_uint = 1; } else if ($1 == "POINTER") sizes[nvars] = sprintf("sizeof(*%s)", $2); else { # DBT, PGDBT sizes[nvars] = \ sprintf("sizeof(u_int32_t) + (%s == NULL ? 0 : %s->size)", \ $2, $2); is_dbt = 1; } nvars++;}/^[ ]*END/ { if (!in_begin) { print "Invalid format: missing BEGIN statement" exit; } # Declare the record type. if (not_buf) { printf("#define\tDB_%s\t%d\n", funcname, rectype) >> HFILE } # Structure declaration. printf("typedef struct _%s_args {\n", funcname) >> HFILE # Here are the required fields for every structure if (not_buf) { printf("\tu_int32_t type;\n\tDB_TXN *txnid;\n") >> HFILE printf("\tDB_LSN prev_lsn;\n") >>HFILE } # Here are the specified fields. for (i = 0; i < nvars; i++) { t = types[i]; if (modes[i] == "POINTER") { ndx = index(t, "*"); t = substr(types[i], 0, ndx - 2); } printf("\t%s\t%s;\n", t, vars[i]) >> HFILE } printf("} %s_args;\n\n", funcname) >> HFILE # Output the log, print and read functions. if (need_log_function) { log_function(); } if (not_buf) { print_function(); } read_function(); # Recovery template if (not_buf) { cmd = sprintf(\ "sed -e s/PREF/%s/ -e s/FUNC/%s/ < template/rec_ctemp >> %s", prefix, thisfunc, TFILE) system(cmd); } # Done writing stuff, reset and continue. in_begin = 0;}END { # End the conditional for the HFILE printf("#endif\n") >> HFILE; if (buf_only == 1) exit # Print initialization routine; function prototype p[1] = sprintf("int %s_init_print %s%s", prefix, "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ", "db_recops, void *), size_t *));"); p[2] = ""; proto_format(p, PFILE); # Create the routine to call __db_add_recovery(print_fn, id) printf("int\n%s_init_print(dbenv, dtabp, dtabsizep)\n", \ prefix) >> PFILE; printf("\tDB_ENV *dbenv;\n") >> PFILE;; printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> PFILE; printf(" db_recops, void *));\n") >> PFILE; printf("\tsize_t *dtabsizep;\n{\n") >> PFILE; # If application-specific, the user will need a prototype for # __db_add_recovery, since they won't have DB's. if (!dbprivate) { printf("\tint __db_add_recovery __P((DB_ENV *,\n") >> PFILE; printf(\"\t int (***)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *),\n") >> PFILE; printf("\t size_t *,\n") >> PFILE; printf(\"\t int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t));\n") \ >> PFILE; } printf("\tint ret;\n\n") >> PFILE; for (i = 0; i < num_funcs; i++) { printf("\tif ((ret = __db_add_recovery(dbenv, ") >> PFILE; printf("dtabp, dtabsizep,\n") >> PFILE; printf("\t %s_print, DB_%s)) != 0)\n", \ funcs[i], funcs[i]) >> PFILE; printf("\t\treturn (ret);\n") >> PFILE; } printf("\treturn (0);\n}\n") >> PFILE; if (prefix == "__ham") printf("#endif /* HAVE_HASH */\n") >> PFILE if (prefix == "__qam") printf("#endif /* HAVE_QUEUE */\n") >> PFILE # We only want to generate *_init_recover functions if this is a # DB-private, rather than application-specific, set of recovery # functions. Application-specific recovery functions should be # dispatched using the DB_ENV->set_app_dispatch callback rather # than a DB dispatch table ("dtab"). if (!dbprivate) exit # Recover initialization routine p[1] = sprintf("int %s_init_recover %s%s", prefix, "__P((DB_ENV *, int (***)(DB_ENV *, DBT *, DB_LSN *, ", "db_recops, void *), size_t *));"); p[2] = ""; proto_format(p, CFILE); # Create the routine to call db_add_recovery(func, id) printf("int\n%s_init_recover(dbenv, dtabp, dtabsizep)\n", \ prefix) >> CFILE; printf("\tDB_ENV *dbenv;\n") >> CFILE; printf("\tint (***dtabp)__P((DB_ENV *, DBT *, DB_LSN *,") >> CFILE; printf(" db_recops, void *));\n") >> CFILE; printf("\tsize_t *dtabsizep;\n{\n\tint ret;\n\n") >> CFILE; for (i = 0; i < num_funcs; i++) { printf("\tif ((ret = __db_add_recovery(dbenv, ") >> CFILE; printf("dtabp, dtabsizep,\n") >> CFILE; printf("\t %s_recover, DB_%s)) != 0)\n", \ funcs[i], funcs[i]) >> CFILE; printf("\t\treturn (ret);\n") >> CFILE; } printf("\treturn (0);\n}\n") >> CFILE;}function log_function(){ # Write the log function; function prototype pi = 1; if (not_buf) { p[pi++] = sprintf("int %s_log", funcname); p[pi++] = " "; if (has_dbp == 1) { p[pi++] = "__P((DB *"; } else { p[pi++] = "__P((DB_ENV *"; } p[pi++] = ", DB_TXN *, DB_LSN *, u_int32_t"; } else { p[pi++] = sprintf("int %s_buf", funcname); p[pi++] = " "; p[pi++] = "__P((u_int8_t *, size_t, size_t *"; } for (i = 0; i < nvars; i++) { if (modes[i] == "DB") continue; p[pi++] = ", "; p[pi++] = sprintf("%s%s%s", (modes[i] == "DBT" || modes[i] == "LOCKS" || modes[i] == "PGDBT") ? "const " : "", types[i], (modes[i] == "DBT" || modes[i] == "LOCKS" || modes[i] == "PGDBT") ? " *" : ""); } p[pi++] = ""; p[pi++] = "));"; p[pi++] = ""; proto_format(p, CFILE); # Function declaration if (not_buf && has_dbp == 1) { printf("int\n%s_log(dbp, txnid, ret_lsnp, flags", \ funcname) >> CFILE; } else if (not_buf) { printf("int\n%s_log(dbenv, txnid, ret_lsnp, flags", \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -