mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
use a local tdb_traverse instead of a ctdb_pulldb to lessen the impact of the system while performing a database backup
(This used to be ctdb commit 48fad9c06185a1f2580473cac02b3722e35c2023)
This commit is contained in:
parent
d793154dbb
commit
ed6ca6a84d
@ -29,6 +29,7 @@
|
||||
#include "../include/ctdb.h"
|
||||
#include "../include/ctdb_private.h"
|
||||
#include "../common/rb_tree.h"
|
||||
#include "db_wrap.h"
|
||||
|
||||
static void usage(void);
|
||||
|
||||
@ -1792,6 +1793,40 @@ struct db_file_header {
|
||||
const char name[MAX_DB_NAME];
|
||||
};
|
||||
|
||||
struct backup_data {
|
||||
struct ctdb_marshall_buffer *records;
|
||||
uint32_t len;
|
||||
uint32_t total;
|
||||
bool traverse_error;
|
||||
};
|
||||
|
||||
static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
|
||||
{
|
||||
struct backup_data *bd = talloc_get_type(private, struct backup_data);
|
||||
struct ctdb_rec_data *rec;
|
||||
|
||||
/* add the record */
|
||||
rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
|
||||
if (rec == NULL) {
|
||||
bd->traverse_error = true;
|
||||
DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
|
||||
return -1;
|
||||
}
|
||||
bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
|
||||
if (bd->records == NULL) {
|
||||
DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
|
||||
bd->traverse_error = true;
|
||||
return -1;
|
||||
}
|
||||
bd->records->count++;
|
||||
memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
|
||||
bd->len += rec->length;
|
||||
talloc_free(rec);
|
||||
|
||||
bd->total++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* backup a database to a file
|
||||
*/
|
||||
@ -1800,8 +1835,9 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
int i, ret;
|
||||
struct ctdb_dbid_map *dbmap=NULL;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
|
||||
TDB_DATA outdata;
|
||||
struct db_file_header dbhdr;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
struct backup_data *bd;
|
||||
int fh;
|
||||
|
||||
if (argc != 2) {
|
||||
@ -1831,34 +1867,49 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* freeze the node */
|
||||
ret = ctdb_ctrl_freeze(ctdb, TIMELIMIT(), options.pnn);
|
||||
if (ret != 0) {
|
||||
DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
|
||||
ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
|
||||
|
||||
ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
|
||||
if (ctdb_db == NULL) {
|
||||
DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
|
||||
if (ret == -1) {
|
||||
DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
|
||||
talloc_free(tmp_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ctdb_ctrl_pulldb(ctdb, options.pnn, dbmap->dbs[i].dbid,
|
||||
CTDB_LMASTER_ANY, tmp_ctx,
|
||||
TIMELIMIT(), &outdata);
|
||||
if (ret != 0) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Unable to copy db from node %u\n", options.pnn));
|
||||
ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
|
||||
|
||||
bd = talloc_zero(tmp_ctx, struct backup_data);
|
||||
if (bd == NULL) {
|
||||
DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
|
||||
talloc_free(tmp_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* thaw the node */
|
||||
ret = ctdb_ctrl_thaw(ctdb, TIMELIMIT(), options.pnn);
|
||||
if (ret != 0) {
|
||||
DEBUG(DEBUG_ERR, ("Unable to thaw node.\n"));
|
||||
ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
|
||||
bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
|
||||
if (bd->records == NULL) {
|
||||
DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
|
||||
talloc_free(tmp_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bd->len = offsetof(struct ctdb_marshall_buffer, data);
|
||||
bd->records->db_id = ctdb_db->db_id;
|
||||
/* traverse the database collecting all records */
|
||||
if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
|
||||
bd->traverse_error) {
|
||||
DEBUG(DEBUG_ERR,("Traverse error\n"));
|
||||
talloc_free(tmp_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb_transaction_cancel(ctdb_db->ltdb->tdb);
|
||||
|
||||
|
||||
fh = open(argv[1], O_RDWR|O_CREAT, 0600);
|
||||
if (fh == -1) {
|
||||
DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
|
||||
@ -1869,7 +1920,7 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
dbhdr.version = DB_VERSION;
|
||||
dbhdr.timestamp = time(NULL);
|
||||
dbhdr.persistent = dbmap->dbs[i].persistent;
|
||||
dbhdr.size = outdata.dsize;
|
||||
dbhdr.size = bd->len;
|
||||
if (strlen(argv[0]) >= MAX_DB_NAME) {
|
||||
DEBUG(DEBUG_ERR,("Too long dbname\n"));
|
||||
talloc_free(tmp_ctx);
|
||||
@ -1877,7 +1928,7 @@ static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
}
|
||||
strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
|
||||
write(fh, &dbhdr, sizeof(dbhdr));
|
||||
write(fh, outdata.dptr, outdata.dsize);
|
||||
write(fh, bd->records, bd->len);
|
||||
|
||||
close(fh);
|
||||
talloc_free(tmp_ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user