*/
#include "includes.h"
-#include "db_wrap.h"
+#include "lib/tdb_wrap/tdb_wrap.h"
#include "tdb.h"
#include "lib/util/dlinklist.h"
#include "system/network.h"
#include "../include/ctdb_private.h"
#include "lib/util/dlinklist.h"
-pid_t ctdbd_pid;
-
/*
allocate a packet for use in client<->daemon communication
*/
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path));
+ strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)-1);
ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
if (ctdb->daemon.sd == -1) {
goto again;
}
+ /* if this is a request for read/write and we have delegations
+ we have to revoke all delegations first
+ */
+ if ((h->header.dmaster == ctdb_db->ctdb->pnn) &&
+ (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
+ ctdb_ltdb_unlock(ctdb_db, key);
+ ret = ctdb_client_force_migration(ctdb_db, key);
+ if (ret != 0) {
+ DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
+ talloc_free(h);
+ return NULL;
+ }
+ goto again;
+ }
+
DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
return h;
}
tdb_flags = TDB_INCOMPATIBLE_HASH;
}
+#ifdef TDB_MUTEX_LOCKING
+ if (!persistent && ctdb->tunable.mutex_enabled == 1) {
+ tdb_flags |= TDB_MUTEX_LOCKING;
+ }
+#endif
+
ret = ctdb_control(ctdb, destnode, tdb_flags,
persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
0, data,
tdb_flags |= TDB_INCOMPATIBLE_HASH;
}
+#ifdef TDB_MUTEX_LOCKING
+ if (!persistent && ctdb->tunable.mutex_enabled == 1) {
+ tdb_flags |= TDB_MUTEX_LOCKING;
+ }
+#endif
+
/* tell ctdb daemon to attach */
ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
}
tdb_flags |= TDB_DISALLOW_NESTING;
- ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
+ ctdb_db->ltdb = tdb_wrap_open(ctdb_db, ctdb_db->db_path, 0, tdb_flags,
+ 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 ctdb_db;
}
+/*
+ * detach from a specific database - client call
+ */
+int ctdb_detach(struct ctdb_context *ctdb, uint32_t db_id)
+{
+ int ret;
+ int32_t status;
+ TDB_DATA data;
+
+ data.dsize = sizeof(db_id);
+ data.dptr = (uint8_t *)&db_id;
+
+ ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_DETACH,
+ 0, data, NULL, NULL, &status, NULL, NULL);
+ if (ret != 0 || status != 0) {
+ return -1;
+ }
+ return 0;
+}
/*
setup a call for a database
ctdb->lastid = INT_MAX-200;
CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
- ret = ctdb_set_socketname(ctdb, CTDB_PATH);
+ ret = ctdb_set_socketname(ctdb, CTDB_SOCKET);
if (ret != 0) {
DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
talloc_free(ctdb);
int32_t res = -1;
uint32_t destnode = state->c->hdr.destnode;
+ outdata.dsize = 0;
+ outdata.dptr = NULL;
+
/* one more node has responded with recmode data */
data->count--;
return id;
}
-static bool server_id_equal(struct server_id *id1, struct server_id *id2)
+/* This is basically a copy from Samba's server_id.*. However, a
+ * dependency chain stops us from using Samba's version, so use a
+ * renamed copy until a better solution is found. */
+static bool ctdb_server_id_equal(struct server_id *id1, struct server_id *id2)
{
if (id1->pid != id2->pid) {
return false;
if (data.dsize % sizeof(struct g_lock_rec) != 0) {
DEBUG(DEBUG_ERR, (__location__ "invalid data size %lu in g_lock record\n",
- data.dsize));
+ (unsigned long)data.dsize));
talloc_free(recs);
return false;
}
struct ctdb_record_handle *h;
struct g_lock_recs *locks;
struct server_id id;
+ struct timeval t_start;
int i;
key.dptr = (uint8_t *)discard_const(keyname);
key.dsize = strlen(keyname) + 1;
+
+ t_start = timeval_current();
+
+again:
+ /* Keep trying for an hour. */
+ if (timeval_elapsed(&t_start) > 3600) {
+ return false;
+ }
+
h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
if (h == NULL) {
return false;
i = 0;
while (i < locks->num) {
- if (server_id_equal(&locks->lock[i].id, &id)) {
+ if (ctdb_server_id_equal(&locks->lock[i].id, &id)) {
/* Internal error */
talloc_free(h);
return false;
id.task_id, id.vnn,
(unsigned long long)id.unique_id));
talloc_free(h);
- return false;
+ goto again;
}
locks->lock = talloc_realloc(locks, locks->lock, struct g_lock_rec,
id = server_id_get(ctdb_db->ctdb, reqid);
for (i=0; i<locks->num; i++) {
- if (server_id_equal(&locks->lock[i].id, &id)) {
+ if (ctdb_server_id_equal(&locks->lock[i].id, &id)) {
if (i < locks->num-1) {
locks->lock[i] = locks->lock[locks->num-1];
}
return 0;
}
+ if (data.dsize == 0) {
+ *seqnum = 0;
+ return 0;
+ }
+
if (data.dsize != sizeof(*seqnum)) {
DEBUG(DEBUG_ERR, (__location__ " Invalid data recived len=%zi\n",
data.dsize));