Commit 60210a73 authored by Rusty Russell's avatar Rusty Russell

tdb2: Make tdb1 use the tdb_file structure.

Because tdb2 allows multiple opens of the same TDB, we separate out
the file information from the struct tdb_context.  Do the same for
tdb1.
parent 2b50be90
...@@ -339,6 +339,9 @@ struct tdb_context { ...@@ -339,6 +339,9 @@ struct tdb_context {
/* Last error we returned. */ /* Last error we returned. */
enum TDB_ERROR last_error; enum TDB_ERROR last_error;
/* The actual file information */
struct tdb_file *file;
/* Open flags passed to tdb_open. */ /* Open flags passed to tdb_open. */
int open_flags; int open_flags;
...@@ -378,8 +381,6 @@ struct tdb_context { ...@@ -378,8 +381,6 @@ struct tdb_context {
/* Direct access information */ /* Direct access information */
struct tdb_access_hdr *access; struct tdb_access_hdr *access;
/* The actual file information */
struct tdb_file *file;
}; };
struct tdb_methods { struct tdb_methods {
......
...@@ -139,8 +139,8 @@ static TDB_DATA get_bytes(struct tdb1_context *tdb, ...@@ -139,8 +139,8 @@ static TDB_DATA get_bytes(struct tdb1_context *tdb,
d.dsize = len; d.dsize = len;
if (tdb->transaction == NULL && tdb->map_ptr != NULL) if (tdb->transaction == NULL && tdb->file->map_ptr != NULL)
d.dptr = (unsigned char *)tdb->map_ptr + off; d.dptr = (unsigned char *)tdb->file->map_ptr + off;
else else
d.dptr = tdb1_alloc_read(tdb, off, d.dsize); d.dptr = tdb1_alloc_read(tdb, off, d.dsize);
return d; return d;
...@@ -149,7 +149,7 @@ static TDB_DATA get_bytes(struct tdb1_context *tdb, ...@@ -149,7 +149,7 @@ static TDB_DATA get_bytes(struct tdb1_context *tdb,
/* Frees data if we're not able to simply use mmap. */ /* Frees data if we're not able to simply use mmap. */
static void put_bytes(struct tdb1_context *tdb, TDB_DATA d) static void put_bytes(struct tdb1_context *tdb, TDB_DATA d)
{ {
if (tdb->transaction == NULL && tdb->map_ptr != NULL) if (tdb->transaction == NULL && tdb->file->map_ptr != NULL)
return; return;
free(d.dptr); free(d.dptr);
} }
...@@ -312,7 +312,7 @@ size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off) ...@@ -312,7 +312,7 @@ size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off)
{ {
size_t len; size_t len;
for (len = 0; off + len < tdb->map_size; len++) { for (len = 0; off + len < tdb->file->map_size; len++) {
char c; char c;
if (tdb->methods->tdb1_read(tdb, off, &c, 1, 0)) if (tdb->methods->tdb1_read(tdb, off, &c, 1, 0))
return 0; return 0;
...@@ -336,7 +336,7 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -336,7 +336,7 @@ int tdb1_check(struct tdb1_context *tdb,
/* Read-only databases use no locking at all: it's best-effort. /* Read-only databases use no locking at all: it's best-effort.
* We may have a write lock already, so skip that case too. */ * We may have a write lock already, so skip that case too. */
if (tdb->read_only || tdb->allrecord_lock.count != 0) { if (tdb->read_only || tdb->file->allrecord_lock.count != 0) {
locked = false; locked = false;
} else { } else {
if (tdb1_lockall_read(tdb) == -1) if (tdb1_lockall_read(tdb) == -1)
...@@ -345,14 +345,14 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -345,14 +345,14 @@ int tdb1_check(struct tdb1_context *tdb,
} }
/* Make sure we know true size of the underlying file. */ /* Make sure we know true size of the underlying file. */
tdb->methods->tdb1_oob(tdb, tdb->map_size + 1, 1); tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
/* Header must be OK: also gets us the recovery ptr, if any. */ /* Header must be OK: also gets us the recovery ptr, if any. */
if (!tdb1_check_header(tdb, &recovery_start)) if (!tdb1_check_header(tdb, &recovery_start))
goto unlock; goto unlock;
/* We should have the whole header, too. */ /* We should have the whole header, too. */
if (tdb->map_size < TDB1_DATA_START(tdb->header.hash_size)) { if (tdb->file->map_size < TDB1_DATA_START(tdb->header.hash_size)) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"File too short for hashes\n"); "File too short for hashes\n");
goto unlock; goto unlock;
...@@ -383,7 +383,7 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -383,7 +383,7 @@ int tdb1_check(struct tdb1_context *tdb,
/* For each record, read it in and check it's ok. */ /* For each record, read it in and check it's ok. */
for (off = TDB1_DATA_START(tdb->header.hash_size); for (off = TDB1_DATA_START(tdb->header.hash_size);
off < tdb->map_size; off < tdb->file->map_size;
off += sizeof(rec) + rec.rec_len) { off += sizeof(rec) + rec.rec_len) {
if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec), if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec),
TDB1_DOCONV()) == -1) TDB1_DOCONV()) == -1)
...@@ -412,7 +412,7 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -412,7 +412,7 @@ int tdb1_check(struct tdb1_context *tdb,
tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING, tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING,
"Dead space at %d-%d (of %u)\n", "Dead space at %d-%d (of %u)\n",
off, off + dead, tdb->map_size); off, off + dead, tdb->file->map_size);
rec.rec_len = dead - sizeof(rec); rec.rec_len = dead - sizeof(rec);
break; break;
case TDB1_RECOVERY_MAGIC: case TDB1_RECOVERY_MAGIC:
......
...@@ -39,18 +39,18 @@ ...@@ -39,18 +39,18 @@
static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe) static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
{ {
struct stat st; struct stat st;
if (len <= tdb->map_size) if (len <= tdb->file->map_size)
return 0; return 0;
if (tdb->flags & TDB_INTERNAL) { if (tdb->flags & TDB_INTERNAL) {
if (!probe) { if (!probe) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb1_oob len %d beyond internal malloc size %d", "tdb1_oob len %d beyond internal malloc size %d",
(int)len, (int)tdb->map_size); (int)len, (int)tdb->file->map_size);
} }
return -1; return -1;
} }
if (fstat(tdb->fd, &st) == -1) { if (fstat(tdb->file->fd, &st) == -1) {
tdb->last_error = TDB_ERR_IO; tdb->last_error = TDB_ERR_IO;
return -1; return -1;
} }
...@@ -69,7 +69,7 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe) ...@@ -69,7 +69,7 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
tdb->last_error = TDB_ERR_IO; tdb->last_error = TDB_ERR_IO;
return -1; return -1;
} }
tdb->map_size = st.st_size; tdb->file->map_size = st.st_size;
tdb1_mmap(tdb); tdb1_mmap(tdb);
return 0; return 0;
} }
...@@ -90,16 +90,17 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off, ...@@ -90,16 +90,17 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
if (tdb->methods->tdb1_oob(tdb, off + len, 0) != 0) if (tdb->methods->tdb1_oob(tdb, off + len, 0) != 0)
return -1; return -1;
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
memcpy(off + (char *)tdb->map_ptr, buf, len); memcpy(off + (char *)tdb->file->map_ptr, buf, len);
} else { } else {
ssize_t written = pwrite(tdb->fd, buf, len, off); ssize_t written = pwrite(tdb->file->fd, buf, len, off);
if ((written != (ssize_t)len) && (written != -1)) { if ((written != (ssize_t)len) && (written != -1)) {
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING, tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
"tdb1_write: wrote only " "tdb1_write: wrote only "
"%d of %d bytes at %d, trying once more", "%d of %d bytes at %d, trying once more",
(int)written, len, off); (int)written, len, off);
written = pwrite(tdb->fd, (const char *)buf+written, written = pwrite(tdb->file->fd,
(const char *)buf+written,
len-written, len-written,
off+written); off+written);
} }
...@@ -139,10 +140,10 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf, ...@@ -139,10 +140,10 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
return -1; return -1;
} }
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
memcpy(buf, off + (char *)tdb->map_ptr, len); memcpy(buf, off + (char *)tdb->file->map_ptr, len);
} else { } else {
ssize_t ret = pread(tdb->fd, buf, len, off); ssize_t ret = pread(tdb->file->fd, buf, len, off);
if (ret != (ssize_t)len) { if (ret != (ssize_t)len) {
/* Ensure ecode is set for log fn. */ /* Ensure ecode is set for log fn. */
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
...@@ -150,7 +151,7 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf, ...@@ -150,7 +151,7 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
"len=%d ret=%d (%s) map_size=%d", "len=%d ret=%d (%s) map_size=%d",
(int)off, (int)len, (int)ret, (int)off, (int)len, (int)ret,
strerror(errno), strerror(errno),
(int)tdb->map_size); (int)tdb->file->map_size);
return -1; return -1;
} }
} }
...@@ -169,9 +170,9 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf, ...@@ -169,9 +170,9 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
static void tdb1_next_hash_chain(struct tdb1_context *tdb, uint32_t *chain) static void tdb1_next_hash_chain(struct tdb1_context *tdb, uint32_t *chain)
{ {
uint32_t h = *chain; uint32_t h = *chain;
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
for (;h < tdb->header.hash_size;h++) { for (;h < tdb->header.hash_size;h++) {
if (0 != *(uint32_t *)(TDB1_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { if (0 != *(uint32_t *)(TDB1_HASH_TOP(h) + (unsigned char *)tdb->file->map_ptr)) {
break; break;
} }
} }
...@@ -193,15 +194,15 @@ int tdb1_munmap(struct tdb1_context *tdb) ...@@ -193,15 +194,15 @@ int tdb1_munmap(struct tdb1_context *tdb)
return 0; return 0;
#if HAVE_MMAP #if HAVE_MMAP
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
int ret; int ret;
ret = munmap(tdb->map_ptr, tdb->map_size); ret = munmap(tdb->file->map_ptr, tdb->file->map_size);
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
#endif #endif
tdb->map_ptr = NULL; tdb->file->map_ptr = NULL;
return 0; return 0;
} }
...@@ -212,25 +213,25 @@ void tdb1_mmap(struct tdb1_context *tdb) ...@@ -212,25 +213,25 @@ void tdb1_mmap(struct tdb1_context *tdb)
#if HAVE_MMAP #if HAVE_MMAP
if (!(tdb->flags & TDB_NOMMAP)) { if (!(tdb->flags & TDB_NOMMAP)) {
tdb->map_ptr = mmap(NULL, tdb->map_size, tdb->file->map_ptr = mmap(NULL, tdb->file->map_size,
PROT_READ|(tdb->read_only? 0:PROT_WRITE), PROT_READ|(tdb->read_only? 0:PROT_WRITE),
MAP_SHARED|MAP_FILE, tdb->fd, 0); MAP_SHARED|MAP_FILE, tdb->file->fd, 0);
/* /*
* NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
*/ */
if (tdb->map_ptr == MAP_FAILED) { if (tdb->file->map_ptr == MAP_FAILED) {
tdb->map_ptr = NULL; tdb->file->map_ptr = NULL;
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING, tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
"tdb1_mmap failed for size %d (%s)", "tdb1_mmap failed for size %d (%s)",
tdb->map_size, strerror(errno)); tdb->file->map_size, strerror(errno));
} }
} else { } else {
tdb->map_ptr = NULL; tdb->file->map_ptr = NULL;
} }
#else #else
tdb->map_ptr = NULL; tdb->file->map_ptr = NULL;
#endif #endif
} }
...@@ -245,12 +246,14 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_ ...@@ -245,12 +246,14 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
return -1; return -1;
} }
if (ftruncate(tdb->fd, size+addition) == -1) { if (ftruncate(tdb->file->fd, size+addition) == -1) {
char b = 0; char b = 0;
ssize_t written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); ssize_t written = pwrite(tdb->file->fd, &b, 1,
(size+addition) - 1);
if (written == 0) { if (written == 0) {
/* try once more, potentially revealing errno */ /* try once more, potentially revealing errno */
written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); written = pwrite(tdb->file->fd, &b, 1,
(size+addition) - 1);
} }
if (written == 0) { if (written == 0) {
/* again - give up, guessing errno */ /* again - give up, guessing errno */
...@@ -271,10 +274,10 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_ ...@@ -271,10 +274,10 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
memset(buf, TDB1_PAD_BYTE, sizeof(buf)); memset(buf, TDB1_PAD_BYTE, sizeof(buf));
while (addition) { while (addition) {
size_t n = addition>sizeof(buf)?sizeof(buf):addition; size_t n = addition>sizeof(buf)?sizeof(buf):addition;
ssize_t written = pwrite(tdb->fd, buf, n, size); ssize_t written = pwrite(tdb->file->fd, buf, n, size);
if (written == 0) { if (written == 0) {
/* prevent infinite loops: try _once_ more */ /* prevent infinite loops: try _once_ more */
written = pwrite(tdb->fd, buf, n, size); written = pwrite(tdb->file->fd, buf, n, size);
} }
if (written == 0) { if (written == 0) {
/* give up, trying to provide a useful errno */ /* give up, trying to provide a useful errno */
...@@ -316,28 +319,28 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size) ...@@ -316,28 +319,28 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
} }
/* must know about any previous expansions by another process */ /* must know about any previous expansions by another process */
tdb->methods->tdb1_oob(tdb, tdb->map_size + 1, 1); tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
/* limit size in order to avoid using up huge amounts of memory for /* limit size in order to avoid using up huge amounts of memory for
* in memory tdbs if an oddball huge record creeps in */ * in memory tdbs if an oddball huge record creeps in */
if (size > 100 * 1024) { if (size > 100 * 1024) {
top_size = tdb->map_size + size * 2; top_size = tdb->file->map_size + size * 2;
} else { } else {
top_size = tdb->map_size + size * 100; top_size = tdb->file->map_size + size * 100;
} }
/* always make room for at least top_size more records, and at /* always make room for at least top_size more records, and at
least 25% more space. if the DB is smaller than 100MiB, least 25% more space. if the DB is smaller than 100MiB,
otherwise grow it by 10% only. */ otherwise grow it by 10% only. */
if (tdb->map_size > 100 * 1024 * 1024) { if (tdb->file->map_size > 100 * 1024 * 1024) {
map_size = tdb->map_size * 1.10; map_size = tdb->file->map_size * 1.10;
} else { } else {
map_size = tdb->map_size * 1.25; map_size = tdb->file->map_size * 1.25;
} }
/* Round the database up to a multiple of the page size */ /* Round the database up to a multiple of the page size */
new_size = MAX(top_size, map_size); new_size = MAX(top_size, map_size);
size = TDB1_ALIGN(new_size, tdb->page_size) - tdb->map_size; size = TDB1_ALIGN(new_size, tdb->page_size) - tdb->file->map_size;
if (!(tdb->flags & TDB_INTERNAL)) if (!(tdb->flags & TDB_INTERNAL))
tdb1_munmap(tdb); tdb1_munmap(tdb);
...@@ -350,20 +353,20 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size) ...@@ -350,20 +353,20 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
/* expand the file itself */ /* expand the file itself */
if (!(tdb->flags & TDB_INTERNAL)) { if (!(tdb->flags & TDB_INTERNAL)) {
if (tdb->methods->tdb1_expand_file(tdb, tdb->map_size, size) != 0) if (tdb->methods->tdb1_expand_file(tdb, tdb->file->map_size, size) != 0)
goto fail; goto fail;
} }
tdb->map_size += size; tdb->file->map_size += size;
if (tdb->flags & TDB_INTERNAL) { if (tdb->flags & TDB_INTERNAL) {
char *new_map_ptr = (char *)realloc(tdb->map_ptr, char *new_map_ptr = (char *)realloc(tdb->file->map_ptr,
tdb->map_size); tdb->file->map_size);
if (!new_map_ptr) { if (!new_map_ptr) {
tdb->map_size -= size; tdb->file->map_size -= size;
goto fail; goto fail;
} }
tdb->map_ptr = new_map_ptr; tdb->file->map_ptr = new_map_ptr;
} else { } else {
/* /*
* We must ensure the file is remapped before adding the space * We must ensure the file is remapped before adding the space
...@@ -380,7 +383,7 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size) ...@@ -380,7 +383,7 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
rec.rec_len = size - sizeof(rec); rec.rec_len = size - sizeof(rec);
/* link it into the free list */ /* link it into the free list */
offset = tdb->map_size - size; offset = tdb->file->map_size - size;
if (tdb1_free(tdb, offset, &rec) == -1) if (tdb1_free(tdb, offset, &rec) == -1)
goto fail; goto fail;
...@@ -438,7 +441,7 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key, ...@@ -438,7 +441,7 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
data.dsize = len; data.dsize = len;
if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { if ((tdb->transaction == NULL) && (tdb->file->map_ptr != NULL)) {
/* /*
* Optimize by avoiding the malloc/memcpy/free, point the * Optimize by avoiding the malloc/memcpy/free, point the
* parser directly at the mmap area. * parser directly at the mmap area.
...@@ -446,7 +449,7 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key, ...@@ -446,7 +449,7 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
if (tdb->methods->tdb1_oob(tdb, offset+len, 0) != 0) { if (tdb->methods->tdb1_oob(tdb, offset+len, 0) != 0) {
return -1; return -1;
} }
data.dptr = offset + (unsigned char *)tdb->map_ptr; data.dptr = offset + (unsigned char *)tdb->file->map_ptr;
return parser(key, data, private_data); return parser(key, data, private_data);
} }
......
This diff is collapsed.
...@@ -76,17 +76,18 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size) ...@@ -76,17 +76,18 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
newdb->rwlocks = TDB1_HASH_RWLOCK_MAGIC; newdb->rwlocks = TDB1_HASH_RWLOCK_MAGIC;
if (tdb->flags & TDB_INTERNAL) { if (tdb->flags & TDB_INTERNAL) {
tdb->map_size = size; tdb->file->fd = -1;
tdb->map_ptr = (char *)newdb; tdb->file->map_size = size;
tdb->file->map_ptr = (char *)newdb;
memcpy(&tdb->header, newdb, sizeof(tdb->header)); memcpy(&tdb->header, newdb, sizeof(tdb->header));
/* Convert the `ondisk' version if asked. */ /* Convert the `ondisk' version if asked. */
TDB1_CONV(*newdb); TDB1_CONV(*newdb);
return 0; return 0;
} }
if (lseek(tdb->fd, 0, SEEK_SET) == -1) if (lseek(tdb->file->fd, 0, SEEK_SET) == -1)
goto fail; goto fail;
if (ftruncate(tdb->fd, 0) == -1) if (ftruncate(tdb->file->fd, 0) == -1)
goto fail; goto fail;
/* This creates an endian-converted header, as if read from disk */ /* This creates an endian-converted header, as if read from disk */
...@@ -95,7 +96,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size) ...@@ -95,7 +96,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
/* Don't endian-convert the magic food! */ /* Don't endian-convert the magic food! */
memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
/* we still have "ret == -1" here */ /* we still have "ret == -1" here */
if (tdb1_write_all(tdb->fd, newdb, size)) if (tdb1_write_all(tdb->file->fd, newdb, size))
ret = 0; ret = 0;
fail: fail:
...@@ -111,7 +112,7 @@ static int tdb1_already_open(dev_t device, ...@@ -111,7 +112,7 @@ static int tdb1_already_open(dev_t device,
struct tdb1_context *i; struct tdb1_context *i;
for (i = tdb1s; i; i = i->next) { for (i = tdb1s; i; i = i->next) {
if (i->device == device && i->inode == ino) { if (i->file->device == device && i->file->inode == ino) {
return 1; return 1;
} }
} }
...@@ -176,10 +177,16 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -176,10 +177,16 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
errno = ENOMEM; errno = ENOMEM;
goto fail; goto fail;
} }
tdb->file = calloc(1, sizeof *tdb->file);
if (!tdb->file) {
free(tdb);
errno = ENOMEM;
goto fail;
}
tdb1_io_init(tdb); tdb1_io_init(tdb);
tdb->fd = -1; tdb->file->fd = -1;
tdb->name = NULL; tdb->name = NULL;
tdb->map_ptr = NULL; tdb->file->map_ptr = NULL;
tdb->flags = tdb1_flags|TDB_VERSION1; tdb->flags = tdb1_flags|TDB_VERSION1;
tdb->open_flags = open_flags; tdb->open_flags = open_flags;
if (log_ctx) { if (log_ctx) {
...@@ -262,7 +269,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -262,7 +269,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
goto internal; goto internal;
} }
if ((tdb->fd = open(name, open_flags, mode)) == -1) { if ((tdb->file->fd = open(name, open_flags, mode)) == -1) {
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb1_open_ex: could not open file %s: %s", "tdb1_open_ex: could not open file %s: %s",
name, strerror(errno)); name, strerror(errno));
...@@ -270,8 +277,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -270,8 +277,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
} }
/* on exec, don't inherit the fd */ /* on exec, don't inherit the fd */
v = fcntl(tdb->fd, F_GETFD, 0); v = fcntl(tdb->file->fd, F_GETFD, 0);
fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC); fcntl(tdb->file->fd, F_SETFD, v | FD_CLOEXEC);
/* ensure there is only one process initialising at once */ /* ensure there is only one process initialising at once */
if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) { if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
...@@ -282,7 +289,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -282,7 +289,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
} }
errno = 0; errno = 0;
if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) if (read(tdb->file->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
|| strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) { || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) {
if (!(open_flags & O_CREAT) || tdb1_new_database(tdb, hash_size) == -1) { if (!(open_flags & O_CREAT) || tdb1_new_database(tdb, hash_size) == -1) {
if (errno == 0) { if (errno == 0) {
...@@ -303,7 +310,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -303,7 +310,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
tdb->flags |= TDB_CONVERT; tdb->flags |= TDB_CONVERT;
tdb1_convert(&tdb->header, sizeof(tdb->header)); tdb1_convert(&tdb->header, sizeof(tdb->header));
} }
if (fstat(tdb->fd, &st) == -1) if (fstat(tdb->file->fd, &st) == -1)
goto fail; goto fail;
if (tdb->header.rwlocks != 0 && if (tdb->header.rwlocks != 0 &&
...@@ -343,9 +350,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -343,9 +350,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
goto fail; goto fail;
} }
tdb->map_size = st.st_size; tdb->file->map_size = st.st_size;
tdb->device = st.st_dev; tdb->file->device = st.st_dev;
tdb->inode = st.st_ino; tdb->file->inode = st.st_ino;
tdb1_mmap(tdb); tdb1_mmap(tdb);
/* if needed, run recovery */ /* if needed, run recovery */
...@@ -370,17 +377,20 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -370,17 +377,20 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
if (!tdb) if (!tdb)
return NULL; return NULL;
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
if (tdb->flags & TDB_INTERNAL) if (tdb->flags & TDB_INTERNAL)
SAFE_FREE(tdb->map_ptr); SAFE_FREE(tdb->file->map_ptr);
else else
tdb1_munmap(tdb); tdb1_munmap(tdb);
} }
if (tdb->fd != -1) if (tdb->file->fd != -1)
if (close(tdb->fd) != 0) if (close(tdb->file->fd) != 0)
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb1_open_ex: failed to close tdb->fd on error!"); "tdb1_open_ex: failed to close tdb->fd on error!");
SAFE_FREE(tdb->lockrecs); if (tdb->file) {
SAFE_FREE(tdb->file->lockrecs);
SAFE_FREE(tdb->file);
}
SAFE_FREE(tdb->name); SAFE_FREE(tdb->name);
SAFE_FREE(tdb); SAFE_FREE(tdb);
errno = save_errno; errno = save_errno;
...@@ -411,18 +421,19 @@ int tdb1_close(struct tdb1_context *tdb) ...@@ -411,18 +421,19 @@ int tdb1_close(struct tdb1_context *tdb)
tdb1_transaction_cancel(tdb); tdb1_transaction_cancel(tdb);
} }
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
if (tdb->flags & TDB_INTERNAL) if (tdb->flags & TDB_INTERNAL)
SAFE_FREE(tdb->map_ptr); SAFE_FREE(tdb->file->map_ptr);
else else
tdb1_munmap(tdb); tdb1_munmap(tdb);
} }
SAFE_FREE(tdb->name); SAFE_FREE(tdb->name);
if (tdb->fd != -1) { if (tdb->file->fd != -1) {
ret = close(tdb->fd); ret = close(tdb->file->fd);
tdb->fd = -1; tdb->file->fd = -1;
} }
SAFE_FREE(tdb->lockrecs); SAFE_FREE(tdb->file->lockrecs);
SAFE_FREE(tdb->file);
/* Remove from contexts list */ /* Remove from contexts list */
for (i = &tdb1s; *i; i = &(*i)->next) { for (i = &tdb1s; *i; i = &(*i)->next) {
......
...@@ -135,12 +135,6 @@ struct tdb1_header { ...@@ -135,12 +135,6 @@ struct tdb1_header {
tdb1_off_t reserved[27]; tdb1_off_t reserved[27];
}; };
struct tdb1_lock_type {
uint32_t off;
uint32_t count;
uint32_t ltype;
};
struct tdb1_traverse_lock { struct tdb1_traverse_lock {
struct tdb1_traverse_lock *next; struct tdb1_traverse_lock *next;
uint32_t off; uint32_t off;
...@@ -174,20 +168,15 @@ struct tdb1_context { ...@@ -174,20 +168,15 @@ struct tdb1_context {
/* Last error we returned. */ /* Last error we returned. */
enum TDB_ERROR last_error; /* error code for last tdb error */ enum TDB_ERROR last_error; /* error code for last tdb error */
void *map_ptr; /* where it is currently mapped */ /* The actual file information */
int fd; /* open file descriptor for the database */ struct tdb_file *file;
tdb1_len_t map_size; /* how much space has been mapped */
int read_only; /* opened read-only */ int read_only; /* opened read-only */
int traverse_read; /* read-only traversal */ int traverse_read; /* read-only traversal */
int traverse_write; /* read-write traversal */ int traverse_write; /* read-write traversal */
struct tdb1_lock_type allrecord_lock; /* .offset == upgradable */
int num_lockrecs;
struct tdb1_lock_type *lockrecs; /* only real locks, all with count>0 */
struct tdb1_header header; /* a cached copy of the header */ struct tdb1_header header; /* a cached copy of the header */
uint32_t flags; /* the flags passed to tdb1_open */ uint32_t flags; /* the flags passed to tdb1_open */
struct tdb1_traverse_lock travlocks; /* current traversal locks */ struct tdb1_traverse_lock travlocks; /* current traversal locks */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
unsigned int (*hash_fn)(TDB_DATA *key); unsigned int (*hash_fn)(TDB_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */ int open_flags; /* flags used in the open - needed by reopen */
const struct tdb1_methods *methods; const struct tdb1_methods *methods;
......
...@@ -96,7 +96,7 @@ char *tdb1_summary(struct tdb1_context *tdb) ...@@ -96,7 +96,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
/* Read-only databases use no locking at all: it's best-effort. /* Read-only databases use no locking at all: it's best-effort.
* We may have a write lock already, so skip that case too. */ * We may have a write lock already, so skip that case too. */
if (tdb->read_only || tdb->allrecord_lock.count != 0) { if (tdb->read_only || tdb->file->allrecord_lock.count != 0) {
locked = false; locked = false;
} else { } else {
if (tdb1_lockall_read(tdb) == -1) if (tdb1_lockall_read(tdb) == -1)
...@@ -117,7 +117,7 @@ char *tdb1_summary(struct tdb1_context *tdb) ...@@ -117,7 +117,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
tally1_init(&uncoal); tally1_init(&uncoal);
for (off = TDB1_DATA_START(tdb->header.hash_size); for (off = TDB1_DATA_START(tdb->header.hash_size);
off < tdb->map_size - 1; off < tdb->file->map_size - 1;
off += sizeof(rec) + rec.rec_len) { off += sizeof(rec) + rec.rec_len) {
if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec), if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec),
TDB1_DOCONV()) == -1) TDB1_DOCONV()) == -1)
...@@ -171,7 +171,7 @@ char *tdb1_summary(struct tdb1_context *tdb) ...@@ -171,7 +171,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
goto unlock; goto unlock;
snprintf(ret, len, SUMMARY_FORMAT1, snprintf(ret, len, SUMMARY_FORMAT1,
tdb->map_size, keys.total+data.total, (tdb1_len_t)tdb->file->map_size, keys.total+data.total,
keys.num, keys.num,
keys.min, tally1_mean(&keys), keys.max, keys.min, tally1_mean(&keys), keys.max,
data.min, tally1_mean(&data), data.max, data.min, tally1_mean(&data), data.max,
...@@ -184,16 +184,16 @@ char *tdb1_summary(struct tdb1_context *tdb) ...@@ -184,16 +184,16 @@ char *tdb1_summary(struct tdb1_context *tdb)
hash.min, tally1_mean(&hash), hash.max, hash.min, tally1_mean(&hash), hash.max,
uncoal.total, uncoal.total,
uncoal.min, tally1_mean(&uncoal), uncoal.max, uncoal.min, tally1_mean(&uncoal), uncoal.max,
keys.total * 100.0 / tdb->map_size, keys.total * 100.0 / tdb->file->map_size,
data.total * 100.0 / tdb->map_size, data.total * 100.0 / tdb->file->map_size,
extra.total * 100.0 / tdb->map_size, extra.total * 100.0 / tdb->file->map_size,
freet.total * 100.0 / tdb->map_size, freet.total * 100.0 / tdb->file->map_size,
dead.total * 100.0 / tdb->map_size, dead.total * 100.0 / tdb->file->map_size,
(keys.num + freet.num + dead.num) (keys.num + freet.num + dead.num)
* (sizeof(struct tdb1_record) + sizeof(uint32_t)) * (sizeof(struct tdb1_record) + sizeof(uint32_t))
* 100.0 / tdb->map_size, * 100.0 / tdb->file->map_size,
tdb->header.hash_size * sizeof(tdb1_off_t) tdb->header.hash_size * sizeof(tdb1_off_t)
* 100.0 / tdb->map_size); * 100.0 / (tdb1_len_t)tdb->file->map_size);
unlock: unlock:
if (locked) { if (locked) {
......
...@@ -698,7 +698,7 @@ static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t ...@@ -698,7 +698,7 @@ static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t
/* the region is not worth adding */ /* the region is not worth adding */
return 0; return 0;
} }
if (length + offset > tdb->map_size) { if (length + offset > tdb->file->map_size) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"tdb1_free_region: adding region beyond" "tdb1_free_region: adding region beyond"
" end of file"); " end of file");
...@@ -774,7 +774,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb) ...@@ -774,7 +774,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
for the recovery area */ for the recovery area */
if (recovery_size == 0) { if (recovery_size == 0) {
/* the simple case - the whole file can be used as a freelist */ /* the simple case - the whole file can be used as a freelist */
data_len = (tdb->map_size - TDB1_DATA_START(tdb->header.hash_size)); data_len = (tdb->file->map_size - TDB1_DATA_START(tdb->header.hash_size));
if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->header.hash_size), data_len) != 0) { if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->header.hash_size), data_len) != 0) {
goto failed; goto failed;
} }
...@@ -792,7 +792,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb) ...@@ -792,7 +792,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
goto failed; goto failed;
} }
/* and the 2nd free list entry after the recovery area - if any */ /* and the 2nd free list entry after the recovery area - if any */
data_len = tdb->map_size - (recovery_head+recovery_size); data_len = tdb->file->map_size - (recovery_head+recovery_size);
if (tdb1_free_region(tdb, recovery_head+recovery_size, data_len) != 0) { if (tdb1_free_region(tdb, recovery_head+recovery_size, data_len) != 0) {
goto failed; goto failed;
} }
......
...@@ -378,7 +378,7 @@ static void transaction1_next_hash_chain(struct tdb1_context *tdb, uint32_t *cha ...@@ -378,7 +378,7 @@ static void transaction1_next_hash_chain(struct tdb1_context *tdb, uint32_t *cha
*/ */
static int transaction1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe) static int transaction1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
{ {
if (len <= tdb->map_size) { if (len <= tdb->file->map_size) {
return 0; return 0;
} }
tdb->last_error = TDB_ERR_IO; tdb->last_error = TDB_ERR_IO;
...@@ -500,8 +500,8 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb) ...@@ -500,8 +500,8 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
/* make sure we know about any file expansions already done by /* make sure we know about any file expansions already done by
anyone else */ anyone else */
tdb->methods->tdb1_oob(tdb, tdb->map_size + 1, 1); tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
tdb->transaction->old_map_size = tdb->map_size; tdb->transaction->old_map_size = tdb->file->map_size;
/* finally hook the io methods, replacing them with /* finally hook the io methods, replacing them with
transaction specific methods */ transaction specific methods */
...@@ -535,18 +535,18 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l ...@@ -535,18 +535,18 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l
} }
#if HAVE_FDATASYNC #if HAVE_FDATASYNC
if (fdatasync(tdb->fd) != 0) { if (fdatasync(tdb->file->fd) != 0) {
#else #else
if (fsync(tdb->fd) != 0) { if (fsync(tdb->file->fd) != 0) {
#endif #endif
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb1_transaction: fsync failed"); "tdb1_transaction: fsync failed");
return -1; return -1;
} }
#if HAVE_MMAP #if HAVE_MMAP
if (tdb->map_ptr) { if (tdb->file->map_ptr) {
tdb1_off_t moffset = offset & ~(tdb->page_size-1); tdb1_off_t moffset = offset & ~(tdb->page_size-1);
if (msync(moffset + (char *)tdb->map_ptr, if (msync(moffset + (char *)tdb->file->map_ptr,
length + (offset - moffset), MS_SYNC) != 0) { length + (offset - moffset), MS_SYNC) != 0) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb1_transaction:" "tdb1_transaction:"
...@@ -577,7 +577,7 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb) ...@@ -577,7 +577,7 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
return 0; return 0;
} }
tdb->map_size = tdb->transaction->old_map_size; tdb->file->map_size = tdb->transaction->old_map_size;
/* free all the transaction blocks */ /* free all the transaction blocks */
for (i=0;i<tdb->transaction->num_blocks;i++) { for (i=0;i<tdb->transaction->num_blocks;i++) {
...@@ -724,11 +724,11 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb, ...@@ -724,11 +724,11 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
/* round up to a multiple of page size */ /* round up to a multiple of page size */
*recovery_max_size = TDB1_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); *recovery_max_size = TDB1_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
*recovery_offset = tdb->map_size; *recovery_offset = tdb->file->map_size;
recovery_head = *recovery_offset; recovery_head = *recovery_offset;
if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size, if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
(tdb->map_size - tdb->transaction->old_map_size) + (tdb->file->map_size - tdb->transaction->old_map_size) +
sizeof(rec) + *recovery_max_size) == -1) { sizeof(rec) + *recovery_max_size) == -1) {
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR, tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_recovery_allocate:" "tdb1_recovery_allocate:"
...@@ -737,11 +737,11 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb, ...@@ -737,11 +737,11 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
} }
/* remap the file (if using mmap) */ /* remap the file (if using mmap) */
methods->tdb1_oob(tdb, tdb->map_size + 1, 1); methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
/* we have to reset the old map size so that we don't try to expand the file /* we have to reset the old map size so that we don't try to expand the file
again in the transaction commit, which would destroy the recovery area */ again in the transaction commit, which would destroy the recovery area */
tdb->transaction->old_map_size = tdb->map_size; tdb->transaction->old_map_size = tdb->file->map_size;
/* write the recovery header offset and sync - we can sync without a race here /* write the recovery header offset and sync - we can sync without a race here
as the magic ptr in the recovery record has not been set */ as the magic ptr in the recovery record has not been set */
...@@ -986,9 +986,9 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb) ...@@ -986,9 +986,9 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
tdb->transaction->prepared = true; tdb->transaction->prepared = true;
/* expand the file to the new size if needed */ /* expand the file to the new size if needed */
if (tdb->map_size != tdb->transaction->old_map_size) { if (tdb->file->map_size != tdb->transaction->old_map_size) {
if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size, if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
tdb->map_size - tdb->file->map_size -
tdb->transaction->old_map_size) == -1) { tdb->transaction->old_map_size) == -1) {
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR, tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_transaction_prepare_commit:" "tdb1_transaction_prepare_commit:"
...@@ -996,8 +996,8 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb) ...@@ -996,8 +996,8 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
_tdb1_transaction_cancel(tdb); _tdb1_transaction_cancel(tdb);
return -1; return -1;
} }
tdb->map_size = tdb->transaction->old_map_size; tdb->file->map_size = tdb->transaction->old_map_size;
methods->tdb1_oob(tdb, tdb->map_size + 1, 1); methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
} }
/* Keep the open lock until the actual commit */ /* Keep the open lock until the actual commit */
...@@ -1123,7 +1123,7 @@ int tdb1_transaction_commit(struct tdb1_context *tdb) ...@@ -1123,7 +1123,7 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
tdb->transaction->num_blocks = 0; tdb->transaction->num_blocks = 0;
/* ensure the new data is on disk */ /* ensure the new data is on disk */
if (transaction1_sync(tdb, 0, tdb->map_size) == -1) { if (transaction1_sync(tdb, 0, tdb->file->map_size) == -1) {
return -1; return -1;
} }
...@@ -1242,7 +1242,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb) ...@@ -1242,7 +1242,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
free(data); free(data);
if (transaction1_sync(tdb, 0, tdb->map_size) == -1) { if (transaction1_sync(tdb, 0, tdb->file->map_size) == -1) {
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR, tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_transaction_recover: failed to sync recovery"); "tdb1_transaction_recover: failed to sync recovery");
return -1; return -1;
......
...@@ -15,12 +15,12 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb, ...@@ -15,12 +15,12 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
return -1; return -1;
} }
if (ftruncate(tdb->fd, size+addition) == -1) { if (ftruncate(tdb->file->fd, size+addition) == -1) {
char b = 0; char b = 0;
ssize_t written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); ssize_t written = pwrite(tdb->file->fd, &b, 1, (size+addition) - 1);
if (written == 0) { if (written == 0) {
/* try once more, potentially revealing errno */ /* try once more, potentially revealing errno */
written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); written = pwrite(tdb->file->fd, &b, 1, (size+addition) - 1);
} }
if (written == 0) { if (written == 0) {
/* again - give up, guessing errno */ /* again - give up, guessing errno */
......
...@@ -28,14 +28,14 @@ static void tdb1_flip_bit(struct tdb1_context *tdb, unsigned int bit) ...@@ -28,14 +28,14 @@ static void tdb1_flip_bit(struct tdb1_context *tdb, unsigned int bit)
unsigned int off = bit / CHAR_BIT; unsigned int off = bit / CHAR_BIT;
unsigned char mask = (1 << (bit % CHAR_BIT)); unsigned char mask = (1 << (bit % CHAR_BIT));
if (tdb->map_ptr) if (tdb->file->map_ptr)
((unsigned char *)tdb->map_ptr)[off] ^= mask; ((unsigned char *)tdb->file->map_ptr)[off] ^= mask;
else { else {
unsigned char c; unsigned char c;
if (pread(tdb->fd, &c, 1, off) != 1) if (pread(tdb->file->fd, &c, 1, off) != 1)
err(1, "pread"); err(1, "pread");
c ^= mask; c ^= mask;
if (pwrite(tdb->fd, &c, 1, off) != 1) if (pwrite(tdb->file->fd, &c, 1, off) != 1)
err(1, "pwrite"); err(1, "pwrite");
} }
} }
...@@ -78,7 +78,7 @@ static void check_test(struct tdb1_context *tdb) ...@@ -78,7 +78,7 @@ static void check_test(struct tdb1_context *tdb)
verifiable += ksize + dsize; verifiable += ksize + dsize;
/* Flip one bit at a time, make sure it detects verifiable bytes. */ /* Flip one bit at a time, make sure it detects verifiable bytes. */
for (i = 0, corrupt = 0; i < tdb->map_size * CHAR_BIT; i++) { for (i = 0, corrupt = 0; i < tdb->file->map_size * CHAR_BIT; i++) {
tdb1_flip_bit(tdb, i); tdb1_flip_bit(tdb, i);
memset(sizes, 0, sizeof(sizes)); memset(sizes, 0, sizeof(sizes));
if (tdb1_check(tdb, check, sizes) != 0) if (tdb1_check(tdb, check, sizes) != 0)
......
...@@ -94,7 +94,7 @@ reset: ...@@ -94,7 +94,7 @@ reset:
if (setjmp(jmpbuf) != 0) { if (setjmp(jmpbuf) != 0) {
/* We're partway through. Simulate our death. */ /* We're partway through. Simulate our death. */
close(tdb->fd); close(tdb->file->fd);
forget_locking1(); forget_locking1();
in_transaction = false; in_transaction = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment