summaryrefslogtreecommitdiffstats
path: root/ctdb/lib/tdb/common/tdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/lib/tdb/common/tdb.c')
-rw-r--r--ctdb/lib/tdb/common/tdb.c99
1 files changed, 48 insertions, 51 deletions
diff --git a/ctdb/lib/tdb/common/tdb.c b/ctdb/lib/tdb/common/tdb.c
index 4d8c5fc59c..fc1f5608fa 100644
--- a/ctdb/lib/tdb/common/tdb.c
+++ b/ctdb/lib/tdb/common/tdb.c
@@ -27,13 +27,13 @@
#include "tdb_private.h"
-TDB_DATA tdb_null;
+_PUBLIC_ TDB_DATA tdb_null;
/*
non-blocking increment of the tdb sequence number if the tdb has been opened using
the TDB_SEQNUM flag
*/
-void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
+_PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
{
tdb_off_t seqnum=0;
@@ -124,6 +124,19 @@ tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t has
static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
+static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ TDB_DATA *dbuf = (TDB_DATA *)private_data;
+
+ if (dbuf->dsize != data.dsize) {
+ return -1;
+ }
+ if (memcmp(dbuf->dptr, data.dptr, data.dsize) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
/* update an entry in place - this only works if the new data size
is <= the old data size and the key exists.
on failure return -1.
@@ -141,18 +154,9 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
* surprisingly common (eg. with a ldb re-index). */
if (rec.key_len == key.dsize &&
rec.data_len == dbuf.dsize &&
- rec.full_hash == hash) {
- TDB_DATA data = _tdb_fetch(tdb, key);
- if (data.dsize == dbuf.dsize &&
- memcmp(data.dptr, dbuf.dptr, data.dsize) == 0) {
- if (data.dptr) {
- free(data.dptr);
- }
- return 0;
- }
- if (data.dptr) {
- free(data.dptr);
- }
+ rec.full_hash == hash &&
+ tdb_parse_record(tdb, key, tdb_update_hash_cmp, &dbuf) == 0) {
+ return 0;
}
/* must be long enough key, data and tailer */
@@ -199,7 +203,7 @@ static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
return ret;
}
-TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
+_PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
{
TDB_DATA ret = _tdb_fetch(tdb, key);
@@ -225,7 +229,7 @@ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
* Return -1 if the record was not found.
*/
-int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
+_PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
int (*parser)(TDB_DATA key, TDB_DATA data,
void *private_data),
void *private_data)
@@ -270,7 +274,7 @@ static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
return 1;
}
-int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
+_PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
{
uint32_t hash = tdb->hash_fn(&key);
int ret;
@@ -429,7 +433,7 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
return ret;
}
-int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
+_PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
{
uint32_t hash = tdb->hash_fn(&key);
int ret;
@@ -473,7 +477,6 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
{
struct tdb_record rec;
tdb_off_t rec_ptr;
- char *p = NULL;
int ret = -1;
/* check for it existing, on insert. */
@@ -503,18 +506,6 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
if (flag != TDB_INSERT)
tdb_delete_hash(tdb, key, hash);
- /* Copy key+value *before* allocating free space in case malloc
- fails and we are left with a dead spot in the tdb. */
-
- if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
- tdb->ecode = TDB_ERR_OOM;
- goto fail;
- }
-
- memcpy(p, key.dptr, key.dsize);
- if (dbuf.dsize)
- memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
-
if (tdb->max_dead_records != 0) {
/*
* Allow for some dead records per hash chain, look if we can
@@ -534,7 +525,10 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
|| tdb->methods->tdb_write(
tdb, rec_ptr + sizeof(rec),
- p, key.dsize + dbuf.dsize) == -1) {
+ key.dptr, key.dsize) == -1
+ || tdb->methods->tdb_write(
+ tdb, rec_ptr + sizeof(rec) + key.dsize,
+ dbuf.dptr, dbuf.dsize) == -1) {
goto fail;
}
goto done;
@@ -577,7 +571,10 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
/* write out and point the top of the hash chain at it */
if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
- || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
+ || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec),
+ key.dptr, key.dsize) == -1
+ || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec)+key.dsize,
+ dbuf.dptr, dbuf.dsize) == -1
|| tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
/* Need to tdb_unallocate() here */
goto fail;
@@ -589,8 +586,6 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
if (ret == 0) {
tdb_increment_seqnum(tdb);
}
-
- SAFE_FREE(p);
return ret;
}
@@ -599,7 +594,7 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
return 0 on success, -1 on failure
*/
-int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
+_PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
{
uint32_t hash;
int ret;
@@ -622,7 +617,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
}
/* Append to an entry. Create if not exist. */
-int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
+_PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
{
uint32_t hash;
TDB_DATA dbuf;
@@ -673,7 +668,7 @@ failed:
return the name of the current tdb file
useful for external logging functions
*/
-const char *tdb_name(struct tdb_context *tdb)
+_PUBLIC_ const char *tdb_name(struct tdb_context *tdb)
{
return tdb->name;
}
@@ -683,7 +678,7 @@ const char *tdb_name(struct tdb_context *tdb)
useful for external routines that want to check the device/inode
of the fd
*/
-int tdb_fd(struct tdb_context *tdb)
+_PUBLIC_ int tdb_fd(struct tdb_context *tdb)
{
return tdb->fd;
}
@@ -692,7 +687,7 @@ int tdb_fd(struct tdb_context *tdb)
return the current logging function
useful for external tdb routines that wish to log tdb errors
*/
-tdb_log_func tdb_log_fn(struct tdb_context *tdb)
+_PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
{
return tdb->log.log_fn;
}
@@ -708,7 +703,7 @@ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
The aim of this sequence number is to allow for a very lightweight
test of a possible tdb change.
*/
-int tdb_get_seqnum(struct tdb_context *tdb)
+_PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb)
{
tdb_off_t seqnum=0;
@@ -716,22 +711,22 @@ int tdb_get_seqnum(struct tdb_context *tdb)
return seqnum;
}
-int tdb_hash_size(struct tdb_context *tdb)
+_PUBLIC_ int tdb_hash_size(struct tdb_context *tdb)
{
return tdb->header.hash_size;
}
-size_t tdb_map_size(struct tdb_context *tdb)
+_PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb)
{
return tdb->map_size;
}
-int tdb_get_flags(struct tdb_context *tdb)
+_PUBLIC_ int tdb_get_flags(struct tdb_context *tdb)
{
return tdb->flags;
}
-void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
+_PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
{
if ((flags & TDB_ALLOW_NESTING) &&
(flags & TDB_DISALLOW_NESTING)) {
@@ -751,7 +746,7 @@ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
tdb->flags |= flags;
}
-void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
+_PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
{
if ((flags & TDB_ALLOW_NESTING) &&
(flags & TDB_DISALLOW_NESTING)) {
@@ -775,7 +770,7 @@ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
/*
enable sequence number handling on an open tdb
*/
-void tdb_enable_seqnum(struct tdb_context *tdb)
+_PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb)
{
tdb->flags |= TDB_SEQNUM;
}
@@ -812,7 +807,7 @@ static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t le
This code carefully steps around the recovery area, leaving it alone
*/
-int tdb_wipe_all(struct tdb_context *tdb)
+_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
{
int i;
tdb_off_t offset = 0;
@@ -886,6 +881,8 @@ int tdb_wipe_all(struct tdb_context *tdb)
}
}
+ tdb_increment_seqnum_nonblock(tdb);
+
if (tdb_unlockall(tdb) != 0) {
TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to unlock\n"));
goto failed;
@@ -919,7 +916,7 @@ static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
/*
repack a tdb
*/
-int tdb_repack(struct tdb_context *tdb)
+_PUBLIC_ int tdb_repack(struct tdb_context *tdb)
{
struct tdb_context *tmp_db;
struct traverse_state state;
@@ -993,7 +990,7 @@ int tdb_repack(struct tdb_context *tdb)
bool tdb_write_all(int fd, const void *buf, size_t count)
{
while (count) {
- size_t ret;
+ ssize_t ret;
ret = write(fd, buf, count);
if (ret < 0)
return false;
@@ -1006,7 +1003,7 @@ bool tdb_write_all(int fd, const void *buf, size_t count)
#ifdef TDB_TRACE
static void tdb_trace_write(struct tdb_context *tdb, const char *str)
{
- if (!tdb_write_alltdb->tracefd, str, strlen(str)) {
+ if (!tdb_write_all(tdb->tracefd, str, strlen(str))) {
close(tdb->tracefd);
tdb->tracefd = -1;
}