summaryrefslogtreecommitdiff
path: root/source3/tdb/tdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/tdb/tdb.c')
-rw-r--r--source3/tdb/tdb.c103
1 files changed, 63 insertions, 40 deletions
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index a1483d42d2..998630cb84 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -88,12 +88,9 @@ static TDB_DATA null_data;
static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
int set, int rw_type, int lck_type)
{
-#if NOLOCK
- return 0;
-#else
struct flock fl;
- if (tdb->fd == -1) return 0; /* for in memory tdb */
+ if (tdb->flags & TDB_NOLOCK) return 0;
if (tdb->read_only) return -1;
@@ -114,7 +111,6 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
return -1;
}
return 0;
-#endif
}
/* lock a list in the database. list -1 is the alloc list */
@@ -126,6 +122,9 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list)
#endif
return -1;
}
+
+ if (tdb->flags & TDB_NOLOCK) return 0;
+
if (tdb->locked[list+1] == 0) {
if (tdb_brlock(tdb, LIST_LOCK_BASE + 4*list, LOCK_SET,
F_WRLCK, F_SETLKW) != 0) {
@@ -146,6 +145,8 @@ static int tdb_unlock(TDB_CONTEXT *tdb, int list)
return -1;
}
+ if (tdb->flags & TDB_NOLOCK) return 0;
+
if (tdb->locked[list+1] == 0) {
#if TDB_DEBUG
printf("not locked %d\n", list);
@@ -197,7 +198,9 @@ static tdb_off tdb_hash_top(TDB_CONTEXT *tdb, unsigned hash)
static int tdb_oob(TDB_CONTEXT *tdb, tdb_off offset)
{
struct stat st;
- if ((offset <= tdb->map_size) || (tdb->fd == -1)) return 0;
+ if (offset <= tdb->map_size) return 0;
+
+ if (tdb->flags & TDB_INTERNAL) return 0;
fstat(tdb->fd, &st);
if (st.st_size <= (size_t)offset) {
@@ -214,9 +217,11 @@ static int tdb_oob(TDB_CONTEXT *tdb, tdb_off offset)
tdb->map_size = st.st_size;
#if HAVE_MMAP
- tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
- tdb->read_only?PROT_READ:PROT_READ|PROT_WRITE,
- MAP_SHARED | MAP_FILE, tdb->fd, 0);
+ if (!(tdb->flags & TDB_NOMMAP)) {
+ tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
+ tdb->read_only?PROT_READ:PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_FILE, tdb->fd, 0);
+ }
#endif
return 0;
}
@@ -340,9 +345,9 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
length = ((tdb->map_size + length + TDB_PAGE_SIZE) & ~(TDB_PAGE_SIZE - 1)) - tdb->map_size;
/* expand the file itself */
- if (tdb->fd != -1) {
- lseek(tdb->fd, tdb->map_size + length - 1, SEEK_SET);
- if (write(tdb->fd, &b, 1) != 1) goto fail;
+ if (!(tdb->flags & TDB_INTERNAL)) {
+ lseek(tdb->fd, tdb->map_size + length - 1, SEEK_SET);
+ if (write(tdb->fd, &b, 1) != 1) goto fail;
}
/* form a new freelist record */
@@ -354,7 +359,7 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
}
#if HAVE_MMAP
- if (tdb->fd != -1 && tdb->map_ptr) {
+ if (!(tdb->flags & TDB_INTERNAL) && tdb->map_ptr) {
munmap(tdb->map_ptr, tdb->map_size);
tdb->map_ptr = NULL;
}
@@ -362,8 +367,8 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
tdb->map_size += length;
- if (tdb->fd == -1) {
- tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size);
+ if (tdb->flags & TDB_INTERNAL) {
+ tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size);
}
/* write it out */
@@ -376,10 +381,10 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
if (ofs_write(tdb, offset, &ptr) == -1) goto fail;
#if HAVE_MMAP
- if (tdb->fd != -1) {
- tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
- PROT_READ|PROT_WRITE,
- MAP_SHARED | MAP_FILE, tdb->fd, 0);
+ if (!(tdb->flags & TDB_NOMMAP)) {
+ tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_FILE, tdb->fd, 0);
}
#endif
@@ -498,8 +503,10 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
memcpy(header.magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
header.version = TDB_VERSION;
header.hash_size = hash_size;
- lseek(tdb->fd, 0, SEEK_SET);
- if (tdb->fd != -1) ftruncate(tdb->fd, 0);
+ if (tdb->fd != -1) {
+ lseek(tdb->fd, 0, SEEK_SET);
+ ftruncate(tdb->fd, 0);
+ }
if (tdb->fd != -1 && write(tdb->fd, &header, sizeof(header)) !=
sizeof(header)) {
@@ -527,14 +534,14 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
} else size += sizeof(tdb_off);
}
- if (tdb->fd == -1) {
- tdb->map_ptr = calloc(size, 1);
- tdb->map_size = size;
- if (tdb->map_ptr == NULL) {
- tdb->ecode = TDB_ERR_IO;
- return -1;
- }
- memcpy(&tdb->header, &header, sizeof(header));
+ if (tdb->flags & TDB_INTERNAL) {
+ tdb->map_ptr = calloc(size,1);
+ tdb->map_size = size;
+ if (tdb->map_ptr == NULL) {
+ tdb->ecode = TDB_ERR_IO;
+ return -1;
+ }
+ memcpy(&tdb->header, &header, sizeof(header));
}
#if TDB_DEBUG
@@ -1141,6 +1148,7 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
tdb.fd = -1;
tdb.name = NULL;
tdb.map_ptr = NULL;
+ tdb.flags = tdb_flags;
if ((open_flags & O_ACCMODE) == O_WRONLY) {
goto fail;
@@ -1150,7 +1158,20 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
tdb.read_only = ((open_flags & O_ACCMODE) == O_RDONLY);
- if (name == NULL) goto in_memory;
+ /* internal databases don't use mmap or locking,
+ and start off cleared */
+ if (tdb.flags & TDB_INTERNAL) {
+ tdb.flags |= (TDB_NOLOCK | TDB_NOMMAP);
+ tdb.flags &= ~TDB_CLEAR_IF_FIRST;
+ }
+
+ /* read only databases don't do locking */
+ if (tdb.read_only) tdb.flags |= TDB_NOLOCK;
+
+ if (tdb.flags & TDB_INTERNAL) {
+ tdb_new_database(&tdb, hash_size);
+ goto internal;
+ }
tdb.fd = open(name, open_flags, mode);
if (tdb.fd == -1) {
@@ -1195,16 +1216,18 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
tdb.locked = (int *)calloc(tdb.header.hash_size+1,
sizeof(tdb.locked[0]));
if (!tdb.locked) {
- goto fail;
+ goto fail;
}
#if HAVE_MMAP
- tdb.map_ptr = (void *)mmap(NULL, st.st_size,
- tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED | MAP_FILE, tdb.fd, 0);
+ if (!(tdb->flags & TDB_NOMMAP)) {
+ tdb.map_ptr = (void *)mmap(NULL, st.st_size,
+ tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_FILE, tdb.fd, 0);
+ }
#endif
- in_memory:
+ internal:
ret = (TDB_CONTEXT *)malloc(sizeof(tdb));
if (!ret) goto fail;
@@ -1236,11 +1259,11 @@ int tdb_close(TDB_CONTEXT *tdb)
if (tdb->locked) free(tdb->locked);
if (tdb->map_ptr) {
- if (tdb->fd != -1) {
- munmap(tdb->map_ptr, tdb->map_size);
- } else {
- free(tdb->map_ptr);
- }
+ if (tdb->flags & TDB_INTERNAL) {
+ free(tdb->map_ptr);
+ } else {
+ munmap(tdb->map_ptr, tdb->map_size);
+ }
}
memset(tdb, 0, sizeof(*tdb));