From: Ronnie Sahlberg Date: Fri, 11 May 2007 00:36:47 +0000 (+1000) Subject: add a control to bump the rsn number for all records in a database X-Git-Tag: tevent-0.9.20~348^2~2723^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9ec30242870c983c79241390767a74194930ef14;p=thirdparty%2Fsamba.git add a control to bump the rsn number for all records in a database use this control from the recovery daemon to ensure that the recmaster always have a higher rsn than andy other node for the records after recovery completes (This used to be ctdb commit 6fb6a8b981a804bfcc460c4481c51c7c647230f6) --- diff --git a/ctdb/common/ctdb_client.c b/ctdb/common/ctdb_client.c index ff7528b1417..9c4d84ad291 100644 --- a/ctdb/common/ctdb_client.c +++ b/ctdb/common/ctdb_client.c @@ -1174,6 +1174,31 @@ int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX * return 0; } +/* + bump rsn on all records + */ +int ctdb_ctrl_bumprsn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid) +{ + int ret; + TDB_DATA indata, outdata; + int32_t res; + + indata.dsize = sizeof(uint32_t); + indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 1); + + ((uint32_t *)(&indata.dptr[0]))[0] = dbid; + + ret = ctdb_control(ctdb, destnode, 0, + CTDB_CONTROL_BUMP_RSN, 0, indata, + mem_ctx, &outdata, &res, &timeout); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for bumprsn failed\n")); + return -1; + } + + return 0; +} + /* ping a node, return number of clients connected */ diff --git a/ctdb/common/ctdb_control.c b/ctdb/common/ctdb_control.c index c64b873368e..48880f84b07 100644 --- a/ctdb/common/ctdb_control.c +++ b/ctdb/common/ctdb_control.c @@ -108,6 +108,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t)); return ctdb_control_clear_db(ctdb, indata); + case CTDB_CONTROL_BUMP_RSN: + CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t)); + return ctdb_control_bump_rsn(ctdb, indata); + case CTDB_CONTROL_PUSH_DB: return ctdb_control_push_db(ctdb, indata); diff --git a/ctdb/common/ctdb_recover.c b/ctdb/common/ctdb_recover.c index 047543d4acd..5f5112d11f8 100644 --- a/ctdb/common/ctdb_recover.c +++ b/ctdb/common/ctdb_recover.c @@ -367,3 +367,41 @@ int32_t ctdb_control_clear_db(struct ctdb_context *ctdb, TDB_DATA indata) return 0; } + +static int traverse_bumprsn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p) +{ + struct ctdb_ltdb_header *header = (struct ctdb_ltdb_header *)data.dptr; + int ret; + + header->rsn++; + + ret = tdb_store(tdb, key, data, TDB_REPLACE); + if (ret) { + DEBUG(0,(__location__ "failed to write tdb data back ret:%d\n",ret)); + return ret; + } + return 0; +} + +int32_t ctdb_control_bump_rsn(struct ctdb_context *ctdb, TDB_DATA indata) +{ + uint32_t dbid = *(uint32_t *)indata.dptr; + struct ctdb_db_context *ctdb_db; + + ctdb_db = find_ctdb_db(ctdb, dbid); + if (!ctdb_db) { + DEBUG(0,(__location__ " Unknown db 0x%08x\n",dbid)); + return -1; + } + + if (tdb_lockall_nonblock(ctdb_db->ltdb->tdb) != 0) { + DEBUG(0,(__location__ " Failed to get nonblock lock on entired db - failing\n")); + return -1; + } + + tdb_traverse(ctdb_db->ltdb->tdb, traverse_bumprsn, NULL); + + tdb_unlockall(ctdb_db->ltdb->tdb); + + return 0; +} diff --git a/ctdb/direct/ctdb_recoverd.c b/ctdb/direct/ctdb_recoverd.c index d7de606b148..50dfd9eabe9 100644 --- a/ctdb/direct/ctdb_recoverd.c +++ b/ctdb/direct/ctdb_recoverd.c @@ -255,6 +255,23 @@ static int update_dmaster_on_all_databases(struct ctdb_context *ctdb, struct ctd } +static int bump_rsn_on_all_databases(struct ctdb_context *ctdb, uint32_t vnn, struct ctdb_dbid_map *dbmap, TALLOC_CTX *mem_ctx) +{ + int i, ret; + + /* bump rsn for all records in all databases */ + for (i=0;inum;i++) { + ret = ctdb_ctrl_bumprsn(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, dbmap->dbids[i]); + if (ret != 0) { + DEBUG(0, (__location__ "Unable to bump rsn for db:0x%08x\n", dbmap->dbids[i])); + return -1; + } + } + + return 0; +} + + static int push_all_local_databases(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap, uint32_t vnn, struct ctdb_dbid_map *dbmap, TALLOC_CTX *mem_ctx) { int i, j, ret; @@ -448,6 +465,14 @@ static int do_recovery(struct ctdb_context *ctdb, struct event_context *ev, } + /* bump the rsn number on all databases + */ + ret = bump_rsn_on_all_databases(ctdb, vnn, dbmap, mem_ctx); + if (ret != 0) { + DEBUG(0, (__location__ "Unable to bump the rsn on all databases\n")); + return -1; + } + /* disable recovery mode */ ret = set_recovery_mode(ctdb, nodemap, CTDB_RECOVERY_NORMAL); diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index f5e02ebdee1..6c94d3574af 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -278,6 +278,11 @@ int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, */ int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid); +/* + bump the rsn number for al records + */ +int ctdb_ctrl_bumprsn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid); + /* write a record on a specific db (this implicitely updates dmaster of the record to locally be the vnn of the node where the control is executed on) */ diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index a22c5c3a5e7..b2119b30972 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -343,6 +343,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS, CTDB_CONTROL_GET_PID, CTDB_CONTROL_GET_RECMASTER, CTDB_CONTROL_SET_RECMASTER, + CTDB_CONTROL_BUMP_RSN, }; @@ -780,5 +781,6 @@ int32_t ctdb_control_pull_db(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DAT int32_t ctdb_control_push_db(struct ctdb_context *ctdb, TDB_DATA indata); int32_t ctdb_control_set_dmaster(struct ctdb_context *ctdb, TDB_DATA indata); int32_t ctdb_control_clear_db(struct ctdb_context *ctdb, TDB_DATA indata); +int32_t ctdb_control_bump_rsn(struct ctdb_context *ctdb, TDB_DATA indata); #endif