📄 ctdb_client.c
字号:
get a lock on a record, and return the records data. Blocks until it gets the lock */struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, TDB_DATA key, TDB_DATA *data){ int ret; struct ctdb_record_handle *h; /* procedure is as follows: 1) get the chain lock. 2) check if we are dmaster 3) if we are the dmaster then return handle 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for reply from ctdbd 5) when we get the reply, goto (1) */ h = talloc_zero(mem_ctx, struct ctdb_record_handle); if (h == NULL) { return NULL; } h->ctdb_db = ctdb_db; h->key = key; h->key.dptr = (unsigned char *)talloc_memdup(h, key.dptr, key.dsize); if (h->key.dptr == NULL) { talloc_free(h); return NULL; } h->data = data; DEBUG(3,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize, (const char *)key.dptr));again: /* step 1 - get the chain lock */ ret = ctdb_ltdb_lock(ctdb_db, key); if (ret != 0) { DEBUG(0, (__location__ " failed to lock ltdb record\n")); talloc_free(h); return NULL; } DEBUG(4,("ctdb_fetch_lock: got chain lock\n")); talloc_set_destructor(h, fetch_lock_destructor); ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data); /* when torturing, ensure we test the remote path */ if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) && random() % 5 == 0) { h->header.dmaster = (uint32_t)-1; } DEBUG(4,("ctdb_fetch_lock: done local fetch\n")); if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->vnn) { ctdb_ltdb_unlock(ctdb_db, key); ret = ctdb_client_force_migration(ctdb_db, key); if (ret != 0) { DEBUG(4,("ctdb_fetch_lock: force_migration failed\n")); talloc_free(h); return NULL; } goto again; } DEBUG(4,("ctdb_fetch_lock: we are dmaster - done\n")); return h;}/* store some data to the record that was locked with ctdb_fetch_lock()*/int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data){ return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);}/* non-locking fetch of a record */int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx, TDB_DATA key, TDB_DATA *data){ struct ctdb_call call; int ret; call.call_id = CTDB_FETCH_FUNC; call.call_data.dptr = NULL; call.call_data.dsize = 0; ret = ctdb_call(ctdb_db, &call); if (ret == 0) { *data = call.reply_data; talloc_steal(mem_ctx, data->dptr); } return ret;}struct ctdb_client_control_state { struct ctdb_context *ctdb; uint32_t reqid; int32_t status; TDB_DATA outdata; enum call_state state; char *errormsg;};/* called when a CTDB_REPLY_CONTROL packet comes in in the client This packet comes in response to a CTDB_REQ_CONTROL request packet. It contains any reply data from the control*/static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr){ struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr; struct ctdb_client_control_state *state; state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_control_state); if (state == NULL) { DEBUG(0,(__location__ " reqid %u not found\n", hdr->reqid)); return; } if (hdr->reqid != state->reqid) { /* we found a record but it was the wrong one */ DEBUG(0, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid)); return; } state->outdata.dptr = c->data; state->outdata.dsize = c->datalen; state->status = c->status; if (c->errorlen) { state->errormsg = talloc_strndup(state, (char *)&c->data[c->datalen], c->errorlen); } talloc_steal(state, c); state->state = CTDB_CALL_DONE;}/* time out handler for ctdb_control */static void timeout_func(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data){ uint32_t *timed_out = (uint32_t *)private_data; *timed_out = 1;}/* destroy a ctdb_control in client*/static int ctdb_control_destructor(struct ctdb_client_control_state *state) { ctdb_reqid_remove(state->ctdb, state->reqid); return 0;}/* send a ctdb control message timeout specifies how long we should wait for a reply. if timeout is NULL we wait indefinitely */int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid, uint32_t opcode, uint32_t flags, TDB_DATA data, TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status, struct timeval *timeout, char **errormsg){ struct ctdb_client_control_state *state; struct ctdb_req_control *c; size_t len; int ret; uint32_t timed_out; if (errormsg) { *errormsg = NULL; } /* if the domain socket is not yet open, open it */ if (ctdb->daemon.sd==-1) { ctdb_socket_connect(ctdb); } state = talloc_zero(ctdb, struct ctdb_client_control_state); CTDB_NO_MEMORY(ctdb, state); state->ctdb = ctdb; state->reqid = ctdb_reqid_new(ctdb, state); state->state = CTDB_CALL_WAIT; state->errormsg = NULL; talloc_set_destructor(state, ctdb_control_destructor); len = offsetof(struct ctdb_req_control, data) + data.dsize; c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL, len, struct ctdb_req_control); CTDB_NO_MEMORY(ctdb, c); c->hdr.reqid = state->reqid; c->hdr.destnode = destnode; c->hdr.reqid = state->reqid; c->opcode = opcode; c->client_id = 0; c->flags = flags; c->srvid = srvid; c->datalen = data.dsize; if (data.dsize) { memcpy(&c->data[0], data.dptr, data.dsize); } ret = ctdb_client_queue_pkt(ctdb, &(c->hdr)); if (ret != 0) { talloc_free(state); return -1; } if (flags & CTDB_CTRL_FLAG_NOREPLY) { talloc_free(state); return 0; } /* semi-async operation */ timed_out = 0; if (timeout && !timeval_is_zero(timeout)) { event_add_timed(ctdb->ev, state, *timeout, timeout_func, &timed_out); } while ((state->state == CTDB_CALL_WAIT) && (timed_out == 0) ){ event_loop_once(ctdb->ev); } if (timed_out) { talloc_free(state); if (errormsg) { (*errormsg) = talloc_strdup(mem_ctx, "control timed out"); } else { DEBUG(0,("ctdb_control timed out\n")); } return -1; } if (outdata) { *outdata = state->outdata; outdata->dptr = (unsigned char *)talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize); } *status = state->status; if (!errormsg && state->errormsg) { DEBUG(0,("ctdb_control error: '%s'\n", state->errormsg)); } if (errormsg && state->errormsg) { (*errormsg) = talloc_move(mem_ctx, &state->errormsg); } talloc_free(state); return 0; }/* a process exists call. Returns 0 if process exists, -1 otherwise */int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid){ int ret; TDB_DATA data; int32_t status; data.dptr = (uint8_t*)&pid; data.dsize = sizeof(pid); ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PROCESS_EXISTS, 0, data, NULL, NULL, &status, NULL, NULL); if (ret != 0) { DEBUG(0,(__location__ " ctdb_control for process_exists failed\n")); return -1; } return status;}/* get remote statistics */int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status){ int ret; TDB_DATA data; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STATISTICS, 0, tdb_null, ctdb, &data, &res, NULL, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for statistics failed\n")); return -1; } if (data.dsize != sizeof(struct ctdb_statistics)) { DEBUG(0,(__location__ " Wrong statistics size %u - expected %u\n", (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics))); return -1; } *status = *(struct ctdb_statistics *)data.dptr; talloc_free(data.dptr); return 0;}/* shutdown a remote ctdb node */int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode){ int ret; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SHUTDOWN, CTDB_CTRL_FLAG_NOREPLY, tdb_null, NULL, NULL, &res, &timeout, NULL); if (ret != 0) { DEBUG(0,(__location__ " ctdb_control for shutdown failed\n")); return -1; } return 0;}/* get vnn map from a remote node */int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap){ int ret; TDB_DATA outdata; int32_t res; struct ctdb_vnn_map_wire *map; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GETVNNMAP, 0, tdb_null, mem_ctx, &outdata, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for getvnnmap failed\n")); return -1; } map = (struct ctdb_vnn_map_wire *)outdata.dptr; if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) || outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) { DEBUG(0,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n")); return -1; } (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map); CTDB_NO_MEMORY(ctdb, *vnnmap); (*vnnmap)->generation = map->generation; (*vnnmap)->size = map->size; (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size); CTDB_NO_MEMORY(ctdb, (*vnnmap)->map); memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size); talloc_free(outdata.dptr); return 0;}/* get the recovery mode of a remote node */int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *recmode){ int ret; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RECMODE, 0, tdb_null, NULL, NULL, &res, &timeout, NULL); if (ret != 0) { DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n")); return -1; } *recmode = res; return 0;}/* set the recovery mode of a remote node */int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode){ int ret; TDB_DATA data; int32_t res; data.dsize = sizeof(uint32_t); data.dptr = (unsigned char *)&recmode; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_RECMODE, 0, data, NULL, NULL, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for setrecmode failed\n")); return -1; } return 0;}/* get the recovery master of a remote node */int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *recmaster){ int ret; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RECMASTER, 0, tdb_null, NULL, NULL, &res, &timeout, NULL); if (ret != 0) { DEBUG(0,(__location__ " ctdb_control for getrecmaster failed\n")); return -1; } *recmaster = res; return 0;}/* set the recovery master of a remote node */int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster){ int ret; TDB_DATA data; int32_t res; ZERO_STRUCT(data); data.dsize = sizeof(uint32_t); data.dptr = (unsigned char *)&recmaster; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_RECMASTER, 0, data, NULL, NULL, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for setrecmaster failed\n")); return -1; } return 0;}/* get a list of databases off a remote node */int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap){ int ret; TDB_DATA outdata; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DBMAP, 0, tdb_null, mem_ctx, &outdata, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for getdbmap failed\n")); return -1; } *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize); talloc_free(outdata.dptr); return 0;}/* get a list of nodes (vnn and flags ) from a remote node */int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap){ int ret; TDB_DATA outdata; int32_t res; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_NODEMAP, 0, tdb_null, mem_ctx, &outdata, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for getnodes failed\n")); return -1; } *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize); talloc_free(outdata.dptr); return 0;}/* set vnn map on a node */int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap){ int ret; TDB_DATA data; int32_t res; struct ctdb_vnn_map_wire *map; size_t len; len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size; map = talloc_size(mem_ctx, len); CTDB_NO_MEMORY_VOID(ctdb, map); map->generation = vnnmap->generation; map->size = vnnmap->size; memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size); data.dsize = len; data.dptr = (uint8_t *)map; ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SETVNNMAP, 0, data, NULL, NULL, &res, &timeout, NULL); if (ret != 0 || res != 0) { DEBUG(0,(__location__ " ctdb_control for setvnnmap failed\n")); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -