mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
- accept an optional set of tdb_flags from clients on open a database,
thus allowing the client to pass through the TDB_NOSYNC flag - ensure that tdb_store() operations on persistent databases that don't have TDB_NOSYNC set happen inside a transaction wrapper, thus making them crash safe (This used to be ctdb commit 49330f97c78ca0669615297ac3d8498651831214)
This commit is contained in:
parent
cd1858d126
commit
dc15a9c1f6
@ -150,7 +150,25 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key,
|
|||||||
memcpy(rec.dptr, header, sizeof(*header));
|
memcpy(rec.dptr, header, sizeof(*header));
|
||||||
memcpy(rec.dptr + sizeof(*header), data.dptr, data.dsize);
|
memcpy(rec.dptr + sizeof(*header), data.dptr, data.dsize);
|
||||||
|
|
||||||
ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
|
/* if this is a persistent database without NOSYNC then we
|
||||||
|
will do this via a transaction */
|
||||||
|
if (ctdb_db->persistent && !(ctdb_db->client_tdb_flags & TDB_NOSYNC)) {
|
||||||
|
ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
|
||||||
|
if (ret != 0) {
|
||||||
|
DEBUG(DEBUG_CRIT, ("Failed to start local transaction\n"));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
|
||||||
|
if (ret != 0) {
|
||||||
|
tdb_transaction_cancel(ctdb_db->ltdb->tdb);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
ret = tdb_transaction_commit(ctdb_db->ltdb->tdb);
|
||||||
|
} else {
|
||||||
|
ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
failed:
|
||||||
talloc_free(rec.dptr);
|
talloc_free(rec.dptr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -400,6 +400,7 @@ struct ctdb_db_context {
|
|||||||
struct ctdb_registered_call *calls; /* list of registered calls */
|
struct ctdb_registered_call *calls; /* list of registered calls */
|
||||||
uint32_t seqnum;
|
uint32_t seqnum;
|
||||||
struct timed_event *te;
|
struct timed_event *te;
|
||||||
|
uint32_t client_tdb_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -910,7 +911,7 @@ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
|
|||||||
void *private_data);
|
void *private_data);
|
||||||
|
|
||||||
int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
||||||
TDB_DATA *outdata, bool persistent);
|
TDB_DATA *outdata, uint64_t tdb_flags, bool persistent);
|
||||||
|
|
||||||
int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
|
int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
|
||||||
ctdb_fn_t fn, int id);
|
ctdb_fn_t fn, int id);
|
||||||
|
@ -206,10 +206,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case CTDB_CONTROL_DB_ATTACH:
|
case CTDB_CONTROL_DB_ATTACH:
|
||||||
return ctdb_control_db_attach(ctdb, indata, outdata, false);
|
return ctdb_control_db_attach(ctdb, indata, outdata, srvid, false);
|
||||||
|
|
||||||
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
|
case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
|
||||||
return ctdb_control_db_attach(ctdb, indata, outdata, true);
|
return ctdb_control_db_attach(ctdb, indata, outdata, srvid, true);
|
||||||
|
|
||||||
case CTDB_CONTROL_SET_CALL: {
|
case CTDB_CONTROL_SET_CALL: {
|
||||||
struct ctdb_control_set_call *sc =
|
struct ctdb_control_set_call *sc =
|
||||||
|
@ -296,12 +296,19 @@ static int ctdb_local_attach(struct ctdb_context *ctdb, const char *db_name, boo
|
|||||||
a client has asked to attach a new database
|
a client has asked to attach a new database
|
||||||
*/
|
*/
|
||||||
int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
||||||
TDB_DATA *outdata, bool persistent)
|
TDB_DATA *outdata, uint64_t tdb_flags,
|
||||||
|
bool persistent)
|
||||||
{
|
{
|
||||||
const char *db_name = (const char *)indata.dptr;
|
const char *db_name = (const char *)indata.dptr;
|
||||||
struct ctdb_db_context *db;
|
struct ctdb_db_context *db;
|
||||||
struct ctdb_node *node = ctdb->nodes[ctdb->pnn];
|
struct ctdb_node *node = ctdb->nodes[ctdb->pnn];
|
||||||
|
|
||||||
|
/* the client can optionally pass additional tdb flags, but we
|
||||||
|
only allow a subset of those on the database in ctdb. Note
|
||||||
|
that tdb_flags is passed in via the (otherwise unused)
|
||||||
|
srvid to the attach control */
|
||||||
|
tdb_flags &= TDB_NOSYNC;
|
||||||
|
|
||||||
/* If the node is inactive it is not part of the cluster
|
/* If the node is inactive it is not part of the cluster
|
||||||
and we should not allow clients to attach to any
|
and we should not allow clients to attach to any
|
||||||
databases
|
databases
|
||||||
@ -317,6 +324,7 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
|||||||
if (db) {
|
if (db) {
|
||||||
outdata->dptr = (uint8_t *)&db->db_id;
|
outdata->dptr = (uint8_t *)&db->db_id;
|
||||||
outdata->dsize = sizeof(db->db_id);
|
outdata->dsize = sizeof(db->db_id);
|
||||||
|
db->client_tdb_flags |= tdb_flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,6 +338,9 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remember the flags the client has specified */
|
||||||
|
db->client_tdb_flags = tdb_flags;
|
||||||
|
|
||||||
outdata->dptr = (uint8_t *)&db->db_id;
|
outdata->dptr = (uint8_t *)&db->db_id;
|
||||||
outdata->dsize = sizeof(db->db_id);
|
outdata->dsize = sizeof(db->db_id);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user