📄 ctdb_client.c
字号:
talloc_free(map); return 0;}/* get all keys and records for a specific database */int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys){ int i, ret; TDB_DATA indata, outdata; struct ctdb_control_pulldb pull; struct ctdb_control_pulldb_reply *reply; struct ctdb_rec_data *rec; int32_t res; pull.db_id = dbid; pull.lmaster = lmaster; indata.dsize = sizeof(struct ctdb_control_pulldb); indata.dptr = (unsigned char *)&pull; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PULL_DB, 0, indata, mem_ctx, &outdata, &res, NULL, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for pulldb failed\n")); return -1; } reply = (struct ctdb_control_pulldb_reply *)outdata.dptr; keys->dbid = reply->db_id; keys->num = reply->count; keys->keys = talloc_array(mem_ctx, TDB_DATA, keys->num); keys->headers = talloc_array(mem_ctx, struct ctdb_ltdb_header, keys->num); keys->data = talloc_array(mem_ctx, TDB_DATA, keys->num); rec = (struct ctdb_rec_data *)&reply->data[0]; for (i=0;i<reply->count;i++) { keys->keys[i].dptr = (unsigned char *)talloc_memdup(mem_ctx, &rec->data[0], rec->keylen); keys->keys[i].dsize = rec->keylen; keys->data[i].dptr = (unsigned char *)talloc_memdup(mem_ctx, &rec->data[keys->keys[i].dsize], rec->datalen); keys->data[i].dsize = rec->datalen; if (keys->data[i].dsize < sizeof(struct ctdb_ltdb_header)) { DEBUG(0,(__location__ " bad ltdb record\n")); return -1; } memcpy(&keys->headers[i], keys->data[i].dptr, sizeof(struct ctdb_ltdb_header)); keys->data[i].dptr += sizeof(struct ctdb_ltdb_header); keys->data[i].dsize -= sizeof(struct ctdb_ltdb_header); rec = (struct ctdb_rec_data *)(rec->length + (uint8_t *)rec); } talloc_free(outdata.dptr); return 0;}/* copy a tdb from one node to another node */int ctdb_ctrl_copydb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t sourcenode, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx){ int ret; TDB_DATA indata, outdata; int32_t res; indata.dsize = 2*sizeof(uint32_t); indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2); ((uint32_t *)(&indata.dptr[0]))[0] = dbid; ((uint32_t *)(&indata.dptr[0]))[1] = lmaster; DEBUG(3,("pulling dbid 0x%x from %u\n", dbid, sourcenode)); ret = ctdb_control(ctdb, sourcenode, 0, CTDB_CONTROL_PULL_DB, 0, indata, mem_ctx, &outdata, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for pulldb failed\n")); return -1; } DEBUG(3,("pushing dbid 0x%x to %u\n", dbid, destnode)); ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PUSH_DB, 0, outdata, mem_ctx, NULL, &res, &timeout, NULL); talloc_free(outdata.dptr); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for pushdb failed\n")); return -1; } DEBUG(3,("copydb for dbid 0x%x done for %u to %u\n", dbid, sourcenode, destnode)); return 0;}/* change dmaster for all keys in the database to the new value */int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster){ int ret; TDB_DATA indata; int32_t res; indata.dsize = 2*sizeof(uint32_t); indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2); ((uint32_t *)(&indata.dptr[0]))[0] = dbid; ((uint32_t *)(&indata.dptr[0]))[1] = dmaster; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DMASTER, 0, indata, NULL, NULL, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for setdmaster failed\n")); return -1; } return 0;}/* ping a node, return number of clients connected */int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode){ int ret; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0, tdb_null, NULL, NULL, &res, NULL, NULL); if (ret != 0) { return -1; } return res;}/* find the real path to a ltdb */int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path){ int ret; int32_t res; TDB_DATA data; data.dptr = (uint8_t *)&dbid; data.dsize = sizeof(dbid); ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GETDBPATH, 0, data, mem_ctx, &data, &res, &timeout, NULL); if (ret != 0 || res != 0) { return -1; } (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize); if ((*path) == NULL) { return -1; } talloc_free(data.dptr); return 0;}/* find the name of a db */int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **name){ int ret; int32_t res; TDB_DATA data; data.dptr = (uint8_t *)&dbid; data.dsize = sizeof(dbid); ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DBNAME, 0, data, mem_ctx, &data, &res, &timeout, NULL); if (ret != 0 || res != 0) { return -1; } (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize); if ((*name) == NULL) { return -1; } talloc_free(data.dptr); return 0;}/* create a database */int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, const char *name){ int ret; int32_t res; TDB_DATA data; data.dptr = (unsigned char *)discard_const(name); data.dsize = strlen(name)+1; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DB_ATTACH, 0, data, mem_ctx, &data, &res, &timeout, NULL); if (ret != 0 || res != 0) { return -1; } return 0;}/* get debug level on a node */int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *level){ int ret; int32_t res; TDB_DATA data; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null, ctdb, &data, &res, NULL, NULL); if (ret != 0 || res != 0) { return -1; } if (data.dsize != sizeof(uint32_t)) { DEBUG(0,("Bad control reply size in ctdb_get_debuglevel (got %u)\n", (unsigned)data.dsize)); return -1; } *level = *(uint32_t *)data.dptr; talloc_free(data.dptr); return 0;}/* set debug level on a node */int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t level){ int ret; int32_t res; TDB_DATA data; data.dptr = (uint8_t *)&level; data.dsize = sizeof(level); ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data, NULL, NULL, &res, NULL, NULL); if (ret != 0 || res != 0) { return -1; } return 0;}/* get a list of connected nodes */uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, struct timeval timeout, TALLOC_CTX *mem_ctx, uint32_t *num_nodes){ struct ctdb_node_map *map=NULL; int ret, i; uint32_t *nodes; *num_nodes = 0; ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map); if (ret != 0) { return NULL; } nodes = talloc_array(mem_ctx, uint32_t, map->num); if (nodes == NULL) { return NULL; } for (i=0;i<map->num;i++) { if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) { nodes[*num_nodes] = map->nodes[i].vnn; (*num_nodes)++; } } return nodes;}/* reset remote status */int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode){ int ret; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null, NULL, NULL, &res, NULL, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for reset statistics failed\n")); return -1; } return 0;}/* attach to a specific database - client call*/struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name){ struct ctdb_db_context *ctdb_db; TDB_DATA data; int ret; int32_t res; ctdb_db = ctdb_db_handle(ctdb, name); if (ctdb_db) { return ctdb_db; } ctdb_db = talloc_zero(ctdb, struct ctdb_db_context); CTDB_NO_MEMORY_NULL(ctdb, ctdb_db); ctdb_db->ctdb = ctdb; ctdb_db->db_name = talloc_strdup(ctdb_db, name); CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name); data.dptr = (unsigned char *)discard_const(name); data.dsize = strlen(name)+1; /* tell ctdb daemon to attach */ ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_ATTACH, 0, data, ctdb_db, &data, &res, NULL, NULL); if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) { DEBUG(0,("Failed to attach to database '%s'\n", name)); talloc_free(ctdb_db); return NULL; } ctdb_db->db_id = *(uint32_t *)data.dptr; talloc_free(data.dptr); ret = ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(2, 0), CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path); if (ret != 0) { DEBUG(0,("Failed to get dbpath for database '%s'\n", name)); talloc_free(ctdb_db); return NULL; } ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, 0, O_RDWR, 0); if (ctdb_db->ltdb == NULL) { ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path); talloc_free(ctdb_db); return NULL; } DLIST_ADD(ctdb->db_list, ctdb_db); return ctdb_db;}/* setup a call for a database */int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id){ TDB_DATA data; int32_t status; struct ctdb_control_set_call c; int ret; struct ctdb_registered_call *call; c.db_id = ctdb_db->db_id; c.fn = fn; c.id = id; data.dptr = (uint8_t *)&c; data.dsize = sizeof(c); ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0, data, NULL, NULL, &status, NULL, NULL); if (ret != 0 || status != 0) { DEBUG(0,("ctdb_set_call failed for call %u\n", id)); return -1; } /* also register locally */ call = talloc(ctdb_db, struct ctdb_registered_call); call->fn = fn; call->id = id; DLIST_ADD(ctdb_db->calls, call); return 0;}struct traverse_state { bool done; uint32_t count; ctdb_traverse_func fn; void *private_data;};/* called on each key during a ctdb_traverse */static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p){ struct traverse_state *state = (struct traverse_state *)p; struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr; TDB_DATA key; if (data.dsize < sizeof(uint32_t) || d->length != data.dsize) { DEBUG(0,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize)); state->done = true; return; } key.dsize = d->keylen; key.dptr = &d->data[0]; data.dsize = d->datalen; data.dptr = &d->data[d->keylen]; if (key.dsize == 0 && data.dsize == 0) { /* end of traverse */ state->done = true; return; } if (state->fn(ctdb, key, data, state->private_data) != 0) { state->done = true; } state->count++;}/* start a cluster wide traverse, calling the supplied fn on each record return the number of records traversed, or -1 on error */int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data){ TDB_DATA data; struct ctdb_traverse_start t; int32_t status; int ret; uint64_t srvid = (getpid() | 0xFLL<<60); struct traverse_state state; state.done = false; state.count = 0; state.private_data = private_data; state.fn = fn; ret = ctdb_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state); if (ret != 0) { DEBUG(0,("Failed to setup traverse handler\n")); return -1; } t.db_id = ctdb_db->db_id; t.srvid = srvid; t.reqid = 0; data.dptr = (uint8_t *)&t; data.dsize = sizeof(t); ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START, 0, data, NULL, NULL, &status, NULL, NULL); if (ret != 0 || status != 0) { DEBUG(0,("ctdb_traverse_all failed\n")); ctdb_remove_message_handler(ctdb_db->ctdb, srvid, &state); return -1; } while (!state.done) { event_loop_once(ctdb_db->ctdb->ev); } ret = ctdb_remove_message_handler(ctdb_db->ctdb, srvid, &state); if (ret != 0) { DEBUG(0,("Failed to remove ctdb_traverse handler\n")); return -1; } return state.count;}/* called on each key during a catdb */static int dumpdb_fn(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p){ FILE *f = (FILE *)p; char *keystr, *datastr; struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr; keystr = hex_encode_talloc(ctdb, key.dptr, key.dsize); datastr = hex_encode_talloc(ctdb, data.dptr+sizeof(*h), data.dsize-sizeof(*h)); fprintf(f, "dmaster: %u\n", h->dmaster); fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn); fprintf(f, "key: %s\ndata: %s\n", keystr, datastr); talloc_free(keystr); talloc_free(datastr); return 0;}/* convenience function to list all keys to stdout */int ctdb_dump_db(struct ctdb_db_context *ctdb_db, FILE *f){ return ctdb_traverse(ctdb_db, dumpdb_fn, f);}/* get the pid of a ctdb daemon */int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid){ int ret; int32_t res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -