Commit 03c18761 authored by Rusty Russell's avatar Rusty Russell

Import from SAMBA's tdb:

commit b90863c0b7b860b006ac49c9396711ff351f777f
Author: Howard Chu <hyc@highlandsun.com>
Date:   Tue Mar 31 13:15:54 2009 +1100

    Add tdb_transaction_prepare_commit()
    
    Using tdb_transaction_prepare_commit() gives us 2-phase commits. This
    allows us to safely commit across multiple tdb databases at once, with
    reasonable transaction semantics
    
    Signed-off-by: tridge@samba.org
parent f83c45bf
...@@ -898,6 +898,16 @@ void tdb_trace(struct tdb_context *tdb, const char *op) ...@@ -898,6 +898,16 @@ void tdb_trace(struct tdb_context *tdb, const char *op)
tdb_trace_end(tdb); tdb_trace_end(tdb);
} }
void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op)
{
char msg[sizeof(tdb_off_t) * 4];
sprintf(msg, "%u ", seqnum);
tdb_trace_write(tdb, msg);
tdb_trace_write(tdb, op);
tdb_trace_end(tdb);
}
void tdb_trace_open(struct tdb_context *tdb, const char *op, void tdb_trace_open(struct tdb_context *tdb, const char *op,
unsigned hash_size, unsigned tdb_flags, unsigned open_flags) unsigned hash_size, unsigned tdb_flags, unsigned open_flags)
{ {
......
...@@ -137,6 +137,7 @@ int tdb_fd(struct tdb_context *tdb); ...@@ -137,6 +137,7 @@ int tdb_fd(struct tdb_context *tdb);
tdb_log_func tdb_log_fn(struct tdb_context *tdb); tdb_log_func tdb_log_fn(struct tdb_context *tdb);
void *tdb_get_logging_private(struct tdb_context *tdb); void *tdb_get_logging_private(struct tdb_context *tdb);
int tdb_transaction_start(struct tdb_context *tdb); int tdb_transaction_start(struct tdb_context *tdb);
int tdb_transaction_prepare_commit(struct tdb_context *tdb);
int tdb_transaction_commit(struct tdb_context *tdb); int tdb_transaction_commit(struct tdb_context *tdb);
int tdb_transaction_cancel(struct tdb_context *tdb); int tdb_transaction_cancel(struct tdb_context *tdb);
int tdb_transaction_recover(struct tdb_context *tdb); int tdb_transaction_recover(struct tdb_context *tdb);
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
#endif #endif
#include "tdb.h" #include "tdb.h"
/* #define TDB_TRACE 1 */ #define TDB_TRACE 1
#if HAVE_GETPAGESIZE #if HAVE_GETPAGESIZE
#define getpagesize() 0x2000 #define getpagesize() 0x2000
...@@ -90,6 +90,7 @@ typedef uint32_t tdb_off_t; ...@@ -90,6 +90,7 @@ typedef uint32_t tdb_off_t;
#ifdef TDB_TRACE #ifdef TDB_TRACE
void tdb_trace(struct tdb_context *tdb, const char *op); void tdb_trace(struct tdb_context *tdb, const char *op);
void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op);
void tdb_trace_open(struct tdb_context *tdb, const char *op, void tdb_trace_open(struct tdb_context *tdb, const char *op,
unsigned hash_size, unsigned tdb_flags, unsigned open_flags); unsigned hash_size, unsigned tdb_flags, unsigned open_flags);
void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret); void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret);
...@@ -107,6 +108,7 @@ void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op, ...@@ -107,6 +108,7 @@ void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret); TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
#else #else
#define tdb_trace(tdb, op) #define tdb_trace(tdb, op)
#define tdb_trace_seqnum(tdb, seqnum, op)
#define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags) #define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags)
#define tdb_trace_ret(tdb, op, ret) #define tdb_trace_ret(tdb, op, ret)
#define tdb_trace_retrec(tdb, op, ret) #define tdb_trace_retrec(tdb, op, ret)
...@@ -216,7 +218,10 @@ struct tdb_context { ...@@ -216,7 +218,10 @@ struct tdb_context {
int page_size; int page_size;
int max_dead_records; int max_dead_records;
int transaction_lock_count; int transaction_lock_count;
#ifdef TDB_TRACE
int tracefd; int tracefd;
uint32_t transaction_prepare_seqnum;
#endif
volatile sig_atomic_t *interrupt_sig_ptr; volatile sig_atomic_t *interrupt_sig_ptr;
}; };
......
...@@ -38,7 +38,7 @@ struct op_table { ...@@ -38,7 +38,7 @@ struct op_table {
void (*enhance_op)(const char *filename, void (*enhance_op)(const char *filename,
struct op op[], unsigned int op_num, char *words[]); struct op op[], unsigned int op_num, char *words[]);
}; };
/* maximum key range = 43, duplicates = 0 */ /* maximum key range = 48, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
...@@ -52,32 +52,32 @@ hash_keyword (register const char *str, register unsigned int len) ...@@ -52,32 +52,32 @@ hash_keyword (register const char *str, register unsigned int len)
{ {
static const unsigned char asso_values[] = static const unsigned char asso_values[] =
{ {
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 20, 51, 25, 56, 56, 56, 56, 56, 56, 56, 20, 56, 30,
5, 0, 0, 5, 5, 51, 51, 0, 0, 0, 5, 0, 0, 5, 5, 56, 56, 0, 0, 0,
20, 51, 20, 51, 51, 0, 5, 0, 51, 0, 20, 56, 20, 56, 56, 0, 5, 0, 56, 0,
51, 5, 51, 51, 51, 51, 51, 51, 51, 51, 56, 5, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
51, 51, 51, 51, 51, 51 56, 56, 56, 56, 56, 56
}; };
return len + asso_values[(unsigned char)str[4]] + asso_values[(unsigned char)str[len - 1]]; return len + asso_values[(unsigned char)str[4]] + asso_values[(unsigned char)str[len - 1]];
} }
...@@ -93,17 +93,17 @@ find_keyword (register const char *str, register unsigned int len) ...@@ -93,17 +93,17 @@ find_keyword (register const char *str, register unsigned int len)
{ {
enum enum
{ {
TOTAL_KEYWORDS = 33, TOTAL_KEYWORDS = 34,
MIN_WORD_LENGTH = 8, MIN_WORD_LENGTH = 8,
MAX_WORD_LENGTH = 25, MAX_WORD_LENGTH = 30,
MIN_HASH_VALUE = 8, MIN_HASH_VALUE = 8,
MAX_HASH_VALUE = 50 MAX_HASH_VALUE = 55
}; };
static const struct op_table wordlist[] = static const struct op_table wordlist[] =
{ {
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 43 "keywords.gperf" #line 44 "keywords.gperf"
{"traverse", OP_TDB_TRAVERSE, op_add_traverse,}, {"traverse", OP_TDB_TRAVERSE, op_add_traverse,},
#line 33 "keywords.gperf" #line 33 "keywords.gperf"
{"tdb_store", OP_TDB_STORE, op_add_store,}, {"tdb_store", OP_TDB_STORE, op_add_store,},
...@@ -115,13 +115,13 @@ find_keyword (register const char *str, register unsigned int len) ...@@ -115,13 +115,13 @@ find_keyword (register const char *str, register unsigned int len)
{"tdb_wipe_all", OP_TDB_WIPE_ALL, op_add_nothing,}, {"tdb_wipe_all", OP_TDB_WIPE_ALL, op_add_nothing,},
#line 20 "keywords.gperf" #line 20 "keywords.gperf"
{"tdb_unlockall", OP_TDB_UNLOCKALL, op_add_nothing,}, {"tdb_unlockall", OP_TDB_UNLOCKALL, op_add_nothing,},
#line 47 "keywords.gperf"
{"tdb_fetch", OP_TDB_FETCH, op_add_key_data,},
#line 48 "keywords.gperf" #line 48 "keywords.gperf"
{"tdb_fetch", OP_TDB_FETCH, op_add_key_data,},
#line 49 "keywords.gperf"
{"tdb_delete", OP_TDB_DELETE, op_add_key_ret,}, {"tdb_delete", OP_TDB_DELETE, op_add_key_ret,},
#line 17 "keywords.gperf" #line 17 "keywords.gperf"
{"tdb_lockall_mark", OP_TDB_LOCKALL_MARK, op_add_nothing,}, {"tdb_lockall_mark", OP_TDB_LOCKALL_MARK, op_add_nothing,},
#line 45 "keywords.gperf" #line 46 "keywords.gperf"
{"tdb_firstkey", OP_TDB_FIRSTKEY, op_add_key,}, {"tdb_firstkey", OP_TDB_FIRSTKEY, op_add_key,},
#line 18 "keywords.gperf" #line 18 "keywords.gperf"
{"tdb_lockall_unmark", OP_TDB_LOCKALL_UNMARK, op_add_nothing,}, {"tdb_lockall_unmark", OP_TDB_LOCKALL_UNMARK, op_add_nothing,},
...@@ -137,35 +137,38 @@ find_keyword (register const char *str, register unsigned int len) ...@@ -137,35 +137,38 @@ find_keyword (register const char *str, register unsigned int len)
{""}, {""},
#line 22 "keywords.gperf" #line 22 "keywords.gperf"
{"tdb_lockall_read_nonblock", OP_TDB_LOCKALL_READ_NONBLOCK, op_add_nothing,}, {"tdb_lockall_read_nonblock", OP_TDB_LOCKALL_READ_NONBLOCK, op_add_nothing,},
#line 42 "keywords.gperf" #line 43 "keywords.gperf"
{"tdb_traverse_end", OP_TDB_TRAVERSE_END, op_analyze_traverse,}, {"tdb_traverse_end", OP_TDB_TRAVERSE_END, op_analyze_traverse,},
#line 38 "keywords.gperf" #line 38 "keywords.gperf"
{"tdb_transaction_cancel", OP_TDB_TRANSACTION_CANCEL, op_analyze_transaction,}, {"tdb_transaction_cancel", OP_TDB_TRANSACTION_CANCEL, op_analyze_transaction,},
#line 41 "keywords.gperf" #line 42 "keywords.gperf"
{"tdb_traverse_start", OP_TDB_TRAVERSE_START, op_add_traverse_start,}, {"tdb_traverse_start", OP_TDB_TRAVERSE_START, op_add_traverse_start,},
{""}, {""},
#line 44 "keywords.gperf" #line 45 "keywords.gperf"
{"traversefn", OP_TDB_TRAVERSE, op_add_traversefn,}, {"traversefn", OP_TDB_TRAVERSE, op_add_traversefn,},
#line 37 "keywords.gperf" #line 37 "keywords.gperf"
{"tdb_transaction_start", OP_TDB_TRANSACTION_START, op_add_transaction,}, {"tdb_transaction_start", OP_TDB_TRANSACTION_START, op_add_transaction,},
#line 39 "keywords.gperf" #line 39 "keywords.gperf"
{"tdb_transaction_commit", OP_TDB_TRANSACTION_COMMIT, op_analyze_transaction,}, {"tdb_transaction_commit", OP_TDB_TRANSACTION_COMMIT, op_analyze_transaction,},
#line 40 "keywords.gperf" #line 41 "keywords.gperf"
{"tdb_traverse_read_start", OP_TDB_TRAVERSE_READ_START, op_add_traverse_start,}, {"tdb_traverse_read_start", OP_TDB_TRAVERSE_READ_START, op_add_traverse_start,},
{""}, {""},
#line 34 "keywords.gperf" #line 34 "keywords.gperf"
{"tdb_append", OP_TDB_APPEND, op_add_append,}, {"tdb_append", OP_TDB_APPEND, op_add_append,},
#line 46 "keywords.gperf" #line 47 "keywords.gperf"
{"tdb_nextkey", OP_TDB_NEXTKEY, op_add_key_data,}, {"tdb_nextkey", OP_TDB_NEXTKEY, op_add_key_data,},
{""}, {""}, {""},
#line 40 "keywords.gperf"
{"tdb_transaction_prepare_commit", OP_TDB_TRANSACTION_PREPARE_COMMIT, op_add_nothing,},
#line 31 "keywords.gperf"
{"tdb_parse_record", OP_TDB_PARSE_RECORD, op_add_key_ret,},
{""}, {""},
#line 24 "keywords.gperf" #line 24 "keywords.gperf"
{"tdb_chainlock", OP_TDB_CHAINLOCK, op_add_chainlock,}, {"tdb_chainlock", OP_TDB_CHAINLOCK, op_add_chainlock,},
{""}, {""},
#line 28 "keywords.gperf" #line 28 "keywords.gperf"
{"tdb_chainunlock", OP_TDB_CHAINUNLOCK, op_analyze_chainlock,}, {"tdb_chainunlock", OP_TDB_CHAINUNLOCK, op_analyze_chainlock,},
#line 31 "keywords.gperf" {""}, {""},
{"tdb_parse_record", OP_TDB_PARSE_RECORD, op_add_key_ret,},
{""},
#line 26 "keywords.gperf" #line 26 "keywords.gperf"
{"tdb_chainlock_mark", OP_TDB_CHAINLOCK_MARK, op_add_key,}, {"tdb_chainlock_mark", OP_TDB_CHAINLOCK_MARK, op_add_key,},
{""}, {""},
......
...@@ -37,6 +37,7 @@ tdb_wipe_all, OP_TDB_WIPE_ALL, op_add_nothing, ...@@ -37,6 +37,7 @@ tdb_wipe_all, OP_TDB_WIPE_ALL, op_add_nothing,
tdb_transaction_start, OP_TDB_TRANSACTION_START, op_add_transaction, tdb_transaction_start, OP_TDB_TRANSACTION_START, op_add_transaction,
tdb_transaction_cancel, OP_TDB_TRANSACTION_CANCEL, op_analyze_transaction, tdb_transaction_cancel, OP_TDB_TRANSACTION_CANCEL, op_analyze_transaction,
tdb_transaction_commit, OP_TDB_TRANSACTION_COMMIT, op_analyze_transaction, tdb_transaction_commit, OP_TDB_TRANSACTION_COMMIT, op_analyze_transaction,
tdb_transaction_prepare_commit, OP_TDB_TRANSACTION_PREPARE_COMMIT, op_add_nothing,
tdb_traverse_read_start, OP_TDB_TRAVERSE_READ_START, op_add_traverse_start, tdb_traverse_read_start, OP_TDB_TRAVERSE_READ_START, op_add_traverse_start,
tdb_traverse_start, OP_TDB_TRAVERSE_START, op_add_traverse_start, tdb_traverse_start, OP_TDB_TRAVERSE_START, op_add_traverse_start,
tdb_traverse_end, OP_TDB_TRAVERSE_END, op_analyze_traverse, tdb_traverse_end, OP_TDB_TRAVERSE_END, op_analyze_traverse,
......
...@@ -116,6 +116,7 @@ enum op_type { ...@@ -116,6 +116,7 @@ enum op_type {
OP_TDB_WIPE_ALL, OP_TDB_WIPE_ALL,
OP_TDB_TRANSACTION_START, OP_TDB_TRANSACTION_START,
OP_TDB_TRANSACTION_CANCEL, OP_TDB_TRANSACTION_CANCEL,
OP_TDB_TRANSACTION_PREPARE_COMMIT,
OP_TDB_TRANSACTION_COMMIT, OP_TDB_TRANSACTION_COMMIT,
OP_TDB_TRAVERSE_READ_START, OP_TDB_TRAVERSE_READ_START,
OP_TDB_TRAVERSE_START, OP_TDB_TRAVERSE_START,
...@@ -764,6 +765,10 @@ unsigned run_ops(struct tdb_context *tdb, ...@@ -764,6 +765,10 @@ unsigned run_ops(struct tdb_context *tdb,
case OP_TDB_TRANSACTION_CANCEL: case OP_TDB_TRANSACTION_CANCEL:
try(tdb_transaction_cancel(tdb), op[file][i].ret); try(tdb_transaction_cancel(tdb), op[file][i].ret);
break; break;
case OP_TDB_TRANSACTION_PREPARE_COMMIT:
try(tdb_transaction_prepare_commit(tdb),
op[file][i].ret);
break;
case OP_TDB_TRANSACTION_COMMIT: case OP_TDB_TRANSACTION_COMMIT:
try(tdb_transaction_commit(tdb), op[file][i].ret); try(tdb_transaction_commit(tdb), op[file][i].ret);
break; break;
......
...@@ -129,13 +129,11 @@ static void addrec_db(void) ...@@ -129,13 +129,11 @@ static void addrec_db(void)
goto next; goto next;
} }
if (in_traverse == 0 && in_transaction && random() % TRANSACTION_PROB == 0) { if (in_traverse == 0 && in_transaction && random() % TRANSACTION_PROB == 0) {
#if 0
if (random() % TRANSACTION_PREPARE_PROB == 0) { if (random() % TRANSACTION_PREPARE_PROB == 0) {
if (tdb_transaction_prepare_commit(db) != 0) { if (tdb_transaction_prepare_commit(db) != 0) {
fatal("tdb_transaction_prepare_commit failed"); fatal("tdb_transaction_prepare_commit failed");
} }
} }
#endif
if (tdb_transaction_commit(db) != 0) { if (tdb_transaction_commit(db) != 0) {
fatal("tdb_transaction_commit failed"); fatal("tdb_transaction_commit failed");
} }
......
This diff is collapsed.
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