return state;
}
-struct db_record *dbwrap_fetch_locked(struct db_context *db,
- TALLOC_CTX *mem_ctx,
- TDB_DATA key)
+static struct db_record *dbwrap_fetch_locked_internal(
+ struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key,
+ struct db_record *(*db_fn)(struct db_context *db, TALLOC_CTX *mem_ctx,
+ TDB_DATA key))
{
struct db_record *rec;
struct dbwrap_lock_order_state *lock_order;
if (lock_order == NULL) {
return NULL;
}
- rec = db->fetch_locked(db, mem_ctx, key);
+ rec = db_fn(db, mem_ctx, key);
if (rec == NULL) {
TALLOC_FREE(lock_order);
return NULL;
return rec;
}
+struct db_record *dbwrap_fetch_locked(struct db_context *db,
+ TALLOC_CTX *mem_ctx,
+ TDB_DATA key)
+{
+ return dbwrap_fetch_locked_internal(db, mem_ctx, key,
+ db->fetch_locked);
+}
+
+struct db_record *dbwrap_try_fetch_locked(struct db_context *db,
+ TALLOC_CTX *mem_ctx,
+ TDB_DATA key)
+{
+ return dbwrap_fetch_locked_internal(
+ db, mem_ctx, key,
+ db->try_fetch_locked
+ ? db->try_fetch_locked : db->fetch_locked);
+}
+
struct dbwrap_fetch_state {
TALLOC_CTX *mem_ctx;
TDB_DATA data;
struct db_record *dbwrap_fetch_locked(struct db_context *db,
TALLOC_CTX *mem_ctx,
TDB_DATA key);
+struct db_record *dbwrap_try_fetch_locked(struct db_context *db,
+ TALLOC_CTX *mem_ctx,
+ TDB_DATA key);
NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key);
NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
dbwrap_cache_validate(ctx);
db->fetch_locked = dbwrap_cache_fetch_locked;
+ db->try_fetch_locked = NULL;
db->traverse = dbwrap_cache_traverse;
db->traverse_read = dbwrap_cache_traverse_read;
db->get_seqnum = dbwrap_cache_get_seqnum;
static struct db_record *fetch_locked_internal(struct db_ctdb_ctx *ctx,
TALLOC_CTX *mem_ctx,
- TDB_DATA key)
+ TDB_DATA key,
+ bool tryonly)
{
struct db_record *result;
struct db_ctdb_rec *crec;
NTSTATUS status;
TDB_DATA ctdb_data;
int migrate_attempts = 0;
+ int lockret;
if (!(result = talloc(mem_ctx, struct db_record))) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(keystr);
}
- if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
+ lockret = tryonly
+ ? tdb_chainlock_nonblock(ctx->wtdb->tdb, key)
+ : tdb_chainlock(ctx->wtdb->tdb, key);
+ if (lockret != 0) {
DEBUG(3, ("tdb_chainlock failed\n"));
TALLOC_FREE(result);
return NULL;
tdb_chainunlock(ctx->wtdb->tdb, key);
talloc_set_destructor(result, NULL);
+ if (tryonly && (migrate_attempts != 0)) {
+ DEBUG(5, ("record migrated away again\n"));
+ TALLOC_FREE(result);
+ return NULL;
+ }
+
migrate_attempts += 1;
DEBUG(10, ("ctdb_data.dptr = %p, dmaster = %u (%u) %u\n",
return db_ctdb_fetch_locked_persistent(ctx, mem_ctx, key);
}
- return fetch_locked_internal(ctx, mem_ctx, key);
+ return fetch_locked_internal(ctx, mem_ctx, key, false);
+}
+
+static struct db_record *db_ctdb_try_fetch_locked(struct db_context *db,
+ TALLOC_CTX *mem_ctx,
+ TDB_DATA key)
+{
+ struct db_ctdb_ctx *ctx = talloc_get_type_abort(db->private_data,
+ struct db_ctdb_ctx);
+
+ if (ctx->transaction != NULL) {
+ return db_ctdb_fetch_locked_transaction(ctx, mem_ctx, key);
+ }
+
+ if (db->persistent) {
+ return db_ctdb_fetch_locked_persistent(ctx, mem_ctx, key);
+ }
+
+ return fetch_locked_internal(ctx, mem_ctx, key, true);
}
/*
result->private_data = (void *)db_ctdb;
result->fetch_locked = db_ctdb_fetch_locked;
+ result->try_fetch_locked = db_ctdb_try_fetch_locked;
result->parse_record = db_ctdb_parse_record;
result->traverse = db_ctdb_traverse;
result->traverse_read = db_ctdb_traverse_read;
result->private_data = ctx;
result->fetch_locked = db_file_fetch_locked;
+ result->try_fetch_locked = NULL;
result->traverse = db_file_traverse;
result->traverse_read = db_file_traverse;
result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
struct db_record *(*fetch_locked)(struct db_context *db,
TALLOC_CTX *mem_ctx,
TDB_DATA key);
+ struct db_record *(*try_fetch_locked)(struct db_context *db,
+ TALLOC_CTX *mem_ctx,
+ TDB_DATA key);
int (*traverse)(struct db_context *db,
int (*f)(struct db_record *rec,
void *private_data),
}
result->fetch_locked = db_rbt_fetch_locked;
+ result->try_fetch_locked = NULL;
result->traverse = db_rbt_traverse;
result->traverse_read = db_rbt_traverse;
result->get_seqnum = db_rbt_get_seqnum;
return 0;
}
-static struct db_record *db_tdb_fetch_locked(struct db_context *db,
- TALLOC_CTX *mem_ctx, TDB_DATA key)
+static struct db_record *db_tdb_fetch_locked_internal(
+ struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
{
struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
struct db_tdb_ctx);
struct tdb_fetch_locked_state state;
- db_tdb_log_key("Locking", key);
-
- if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
- DEBUG(3, ("tdb_chainlock failed\n"));
- return NULL;
- }
-
state.mem_ctx = mem_ctx;
state.result = NULL;
return state.result;
}
+static struct db_record *db_tdb_fetch_locked(
+ struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
+{
+ struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
+ struct db_tdb_ctx);
+
+ db_tdb_log_key("Locking", key);
+ if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
+ DEBUG(3, ("tdb_chainlock failed\n"));
+ return NULL;
+ }
+ return db_tdb_fetch_locked_internal(db, mem_ctx, key);
+}
+
+static struct db_record *db_tdb_try_fetch_locked(
+ struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
+{
+ struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
+ struct db_tdb_ctx);
+
+ db_tdb_log_key("Trying to lock", key);
+ if (tdb_chainlock_nonblock(ctx->wtdb->tdb, key) != 0) {
+ DEBUG(3, ("tdb_chainlock_nonblock failed\n"));
+ return NULL;
+ }
+ return db_tdb_fetch_locked_internal(db, mem_ctx, key);
+}
+
+
static int db_tdb_exists(struct db_context *db, TDB_DATA key)
{
struct db_tdb_ctx *ctx = talloc_get_type_abort(
}
result->fetch_locked = db_tdb_fetch_locked;
+ result->try_fetch_locked = db_tdb_try_fetch_locked;
result->traverse = db_tdb_traverse;
result->traverse_read = db_tdb_traverse_read;
result->parse_record = db_tdb_parse;