diff options
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | doc/gdbm.texinfo | 79 | ||||
-rw-r--r-- | src/gdbm.h.in | 30 | ||||
-rw-r--r-- | src/gdbmconst.h | 23 | ||||
-rw-r--r-- | src/gdbmdefs.h | 3 | ||||
-rw-r--r-- | src/gdbmopen.c | 11 | ||||
-rw-r--r-- | src/gdbmreorg.c | 2 | ||||
-rw-r--r-- | src/gdbmsetopt.c | 114 | ||||
-rw-r--r-- | src/mmap.c | 10 |
9 files changed, 228 insertions, 62 deletions
@@ -1,5 +1,23 @@ 2011-08-11 Sergey Poznyakoff <gray@gnu.org.ua> + Improve gdbm_setopt interface. + + * src/gdbm.h.in (GDBM_OPENMASK): New constant. + * src/gdbmconst.h: Remove constants duplicated in + gdbm.h.in. + * src/gdbmdefs.h (gdbm_file_info) <allow_mmap> + <mmap_inited>: Replace with a single member: memory_mapping. + All callers updated. + (GDBM_SETCACHESIZE,GDBM_SETSYNCMODE) + (GDBM_SETCENTFREE,GDBM_SETCOALESCEBLKS): New option names. + (GDBM_SETMMAP,GDBM_GETMMAP,GDBM_GETFLAGS) + (GDBM_GETCACHESIZE,GDBM_GETSYNCMODE,GDBM_GETCENTFREE) + (GDBM_GETCOALESCEBLKS,GDBM_GETMAXMAPSIZE): New option codes. + * src/gdbmsetopt.c: Implement new options. + * doc/gdbm.texinfo: Document new options. + +2011-08-11 Sergey Poznyakoff <gray@gnu.org.ua> + Improve memory mapping support. The new code is more flexible and performs better when diff --git a/doc/gdbm.texinfo b/doc/gdbm.texinfo index 5dc8a97..04efeea 100644 --- a/doc/gdbm.texinfo +++ b/doc/gdbm.texinfo @@ -739,7 +739,7 @@ open database. @deftypefn {gdbm interface} int gdbm_setopt (GDBM_FILE @var{dbf}, int @var{option}, @ void *@var{value}, int @var{size}) -Sets an option on the database. +Sets an option on the database or returns the value of an option. The parameters are: @@ -747,9 +747,10 @@ The parameters are: @item dbf The pointer returned by @code{gdbm_open}. @item option -The option to be set. +The option to be set or retreived. @item value -A pointer to the value to which @var{option} will be set. +A pointer to the value to which @var{option} will be set or where to +place the option value (depending on the option). @item size The length of the data pointed to by @var{value}. @end table @@ -759,11 +760,29 @@ The valid options are: @table @asis @kwindex GDBM_CACHESIZE -@item GDBM_CACHESIZE +@kwindex GDBM_SETCACHESIZE +@item GDBM_SETCACHESIZE +@itemx GDBM_CACHESIZE Set the size of the internal bucket cache. This option may only be set once on each GDBM_FILE descriptor, and is set automatically to 100 upon the first access to the database. The @var{value} should point -to an integer holding the desired cache size. +to a @code{size_t} holding the desired cache size. + +The @samp{GDBM_CACHESIZE} option is provided for compatibility with +earlier versions. + +@kwindex GDBM_GETCACHESIZE +@item GDBM_GETCACHESIZE +Return the size of the internal bucket cache. The @var{value} should +point to a @code{size_t} variable, where the size will be stored. + +@kwindex GDBM_GETFLAGS +@item GDBM_GETFLAGS +Return the flags describing the state of the database. The @var{value} should +point to a @code{int} variable where to store the flags. The return +is the same as the flags used when opening the database (@pxref{Open, +gdbm_open}), except that it reflects the current state (which may have +been altered by another calls to @code{gdbm_setopt}. @kwindex GDBM_FASTMODE @item GDBM_FASTMODE @@ -773,22 +792,34 @@ to an integer: @samp{TRUE} to enable fast mode, and @samp{FALSE} to disable it. This option is retained for compatibility with previous versions of -@code{gdbm}. Its effect is the reverse of @code{GDBM_SYNCMODE} +@code{gdbm}. Its effect is the reverse of @code{GDBM_SETSYNCMODE} (see below). +@kwindex GDBM_SETSYNCMODE @kwindex GDBM_SYNCMODE -@item GDBM_SYNCMODE +@item GDBM_SETSYNCMODE +@itemx GDBM_SYNCMODE Turn on or off file system synchronization operations. This setting defaults to off. The @var{value} should point to an integer: @samp{TRUE} to turn synchronization on, and @samp{FALSE} to turn it off. Note, that this option is a reverse of @code{GDBM_FASTMODE}, -i.e. calling @code{GDBM_SYNCMODE} with @samp{TRUE} has the same effect +i.e. calling @code{GDBM_SETSYNCMODE} with @samp{TRUE} has the same effect as calling @code{GDBM_FASTMODE} with @samp{FALSE}. +The @samp{GDBM_SYNCMODE} option is provided for compatibility with +earlier versions. + +@kwindex GDBM_GETSYNCMODE +@item GDBM_GETSYNCMODE +Return the current synchronization status. The @var{value} should +point to an @code{int} where the status will be stored. + +@kwindex GDBM_SETCENTFREE @kwindex GDBM_CENTFREE -@item GDBM_CENTFREE +@item GDBM_SETCENTFREE +@itemx GDBM_CENTFREE @emph{NOTICE: This feature is still under study.} Set central free block pool to either on or off. The default is off, @@ -798,8 +829,13 @@ set, this option causes all subsequent free blocks to be placed in the more quickly. The @var{value} should point to an integer: @samp{TRUE} to turn central block pool on, and @samp{FALSE} to turn it off. +The @samp{GDBM_CENTFREE} option is provided for compatibility with +earlier versions. + +@kwindex GDBM_SETCOALESCEBLKS @kwindex GDBM_COALESCEBLKS -@item GDBM_COALESCEBLKS +@item GDBM_SETCOALESCEBLKS +@itemx GDBM_COALESCEBLKS @emph{NOTICE: This feature is still under study.} Set free block merging to either on or off. The default is off, which @@ -810,13 +846,34 @@ used in conjunction with GDBM_CENTFREE. The @var{value} should point to an integer: @samp{TRUE} to turn free block merging on, and @samp{FALSE} to turn it off. +@kwindex GDBM_GETCOALESCEBLKS +@item GDBM_GETCOALESCEBLKS +Return the current status of free block merging. The @var{value} should +point to an @code{int} where the status will be stored. + @kwindex GDBM_SETMAXMAPSIZE @item GDBM_SETMAXMAPSIZE -Sets maximum size of the memory mapped region. The @var{value} should +Sets maximum size of a memory mapped region. The @var{value} should point to a value of type @code{size_t}, @code{unsigned long} or @code{unsigned}. The actual value is rounded to the nearest page boundary (the page size is obtained from @code{sysconf(_SC_PAGESIZE)}). + +@kwindex GDBM_GETMAXMAPSIZE +@item GDBM_GETMAXMAPSIZE +Return the maximum size of a memory mapped region. The @var{value} should +point to a value of type @code{size_t} where to return the data. + +@kwindex GDBM_SETMMAP +@item GDBM_SETMMAP +Enable or disable memory mapping mode. The @var{value} should point +to an integer: @samp{TRUE} to enable memory mapping or @samp{FALSE} to +disable it. + +@kwindex GDBM_GETMMAP +@item GDBM_GETMMAP +Check whether memory mapping is enabled. The @var{value} should point +to an integer where to return the status. @end table The return value will be @samp{-1} upon failure, or @samp{0} upon diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 8eaee79..da88777 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -35,6 +35,8 @@ #define GDBM_WRITER 1 /* A writer. */ #define GDBM_WRCREAT 2 /* A writer. Create the db if needed. */ #define GDBM_NEWDB 3 /* A writer. Always create a new db. */ +#define GDBM_OPENMASK 7 /* Mask for the above. */ + #define GDBM_FAST 0x10 /* Write fast! => No fsyncs. OBSOLETE. */ #define GDBM_SYNC 0x20 /* Sync operations to the disk. */ #define GDBM_NOLOCK 0x40 /* Don't do file locking operations. */ @@ -46,12 +48,28 @@ #define GDBM_REPLACE 1 /* Always replace old data with new. */ /* Parameters to gdbm_setopt, specifing the type of operation to perform. */ -#define GDBM_CACHESIZE 1 /* Set the cache size. */ -#define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */ -#define GDBM_SYNCMODE 3 /* Turn on or off sync operations. */ -#define GDBM_CENTFREE 4 /* Keep all free blocks in the header. */ -#define GDBM_COALESCEBLKS 5 /* Attempt to coalesce free blocks. */ -#define GDBM_SETMAXMAPSIZE 6 /* Set maximum mapped memory size */ +#define GDBM_SETCACHESIZE 1 /* Set the cache size. */ +#define GDBM_FASTMODE 2 /* Toggle fast mode. OBSOLETE. */ +#define GDBM_SETSYNCMODE 3 /* Turn on or off sync operations. */ +#define GDBM_SETCENTFREE 4 /* Keep all free blocks in the header. */ +#define GDBM_SETCOALESCEBLKS 5 /* Attempt to coalesce free blocks. */ +#define GDBM_SETMAXMAPSIZE 6 /* Set maximum mapped memory size */ +#define GDBM_SETMMAP 7 + +/* Compatibility defines: */ +#define GDBM_CACHESIZE GDBM_SETCACHESIZE +#define GDBM_SYNCMODE GDBM_SETSYNCMODE +#define GDBM_CENTFREE GDBM_SETCENTFREE +#define GDBM_COALESCEBLKS GDBM_SETCENTFREE + +#define GDBM_GETFLAGS 8 +#define GDBM_GETMMAP 9 +#define GDBM_GETCACHESIZE 10 +#define GDBM_GETSYNCMODE 11 +#define GDBM_GETCENTFREE 12 +#define GDBM_GETCOALESCEBLKS 13 +#define GDBM_GETMAXMAPSIZE 14 + /* The data and key structure. */ typedef struct { diff --git a/src/gdbmconst.h b/src/gdbmconst.h index 7a3f5b9..24eac5f 100644 --- a/src/gdbmconst.h +++ b/src/gdbmconst.h @@ -35,29 +35,6 @@ #define GDBM_MAGIC32_SWAP 0xcd9a5713 /* MAGIC32 swapped. */ #define GDBM_MAGIC64_SWAP 0xcf9a5713 /* MAGIC64 swapped. */ -/* Parameters to gdbm_open. */ -#define GDBM_READER 0 /* READERS only. */ -#define GDBM_WRITER 1 /* READERS and WRITERS. Can not create. */ -#define GDBM_WRCREAT 2 /* If not found, create the db. */ -#define GDBM_NEWDB 3 /* ALWAYS create a new db. (WRITER) */ -#define GDBM_OPENMASK 7 /* Mask for the above. */ -#define GDBM_FAST 0x10 /* Write fast! => No fsyncs. OBSOLETE. */ -#define GDBM_SYNC 0x20 /* Sync operations to the disk. */ -#define GDBM_NOLOCK 0x40 /* Don't do file locking operations. */ -#define GDBM_NOMMAP 0x80 /* Don't use mmap(). */ - -/* Parameters to gdbm_store for simple insertion or replacement in the - case a key to store is already in the database. */ -#define GDBM_INSERT 0 /* Do not overwrite data in the database. */ -#define GDBM_REPLACE 1 /* Replace the old value with the new value. */ - -/* Parameters to gdbm_setopt, specifing the type of operation to perform. */ -#define GDBM_CACHESIZE 1 /* Set the cache size. */ -#define GDBM_FASTMODE 2 /* Turn on or off fast mode. OBSOLETE. */ -#define GDBM_SYNCMODE 3 /* Turn on or off sync operations. */ -#define GDBM_CENTFREE 4 /* Keep all free blocks in the header. */ -#define GDBM_COALESCEBLKS 5 /* Attempt to coalesce free blocks. */ - /* In freeing blocks, we will ignore any blocks smaller (and equal) to IGNORE_SIZE number of bytes. */ #define IGNORE_SIZE 4 diff --git a/src/gdbmdefs.h b/src/gdbmdefs.h index 2221aa5..e45abf8 100644 --- a/src/gdbmdefs.h +++ b/src/gdbmdefs.h @@ -150,8 +150,7 @@ struct gdbm_file_info { unsigned file_locking :1; /* Whether or not we're allowing mmap() use. */ - unsigned allow_mmap :1; - unsigned mmap_inited :1; + unsigned memory_mapping :1; /* Type of file locking in use. */ enum { LOCKING_NONE = 0, LOCKING_FLOCK, LOCKING_LOCKF, diff --git a/src/gdbmopen.c b/src/gdbmopen.c index a110d64..b1b38b4 100644 --- a/src/gdbmopen.c +++ b/src/gdbmopen.c @@ -84,7 +84,7 @@ gdbm_open (const char *file, int block_size, int flags, int mode, dbf->bucket_cache = NULL; dbf->cache_size = 0; - dbf->mmap_inited = FALSE; + dbf->memory_mapping = FALSE; dbf->mapped_size_max = SIZE_T_MAX; dbf->mapped_region = NULL; dbf->mapped_size = 0; @@ -109,7 +109,6 @@ gdbm_open (const char *file, int block_size, int flags, int mode, dbf->file_locking = TRUE; /* Default to doing file locking. */ dbf->central_free = FALSE; /* Default to not using central_free. */ dbf->coalesce_blocks = FALSE; /* Default to not coalescing blocks. */ - dbf->allow_mmap = TRUE; /* Default to using mmap(). */ /* GDBM_FAST used to determine whether or not we set fast_write. */ if (flags & GDBM_SYNC) @@ -121,10 +120,6 @@ gdbm_open (const char *file, int block_size, int flags, int mode, { dbf->file_locking = FALSE; } - if (flags & GDBM_NOMMAP) - { - dbf->allow_mmap = FALSE; - } /* Open the file. */ need_trunc = FALSE; @@ -395,10 +390,10 @@ gdbm_open (const char *file, int block_size, int flags, int mode, } #if HAVE_MMAP - if (dbf->allow_mmap) + if (!(flags & GDBM_NOMMAP)) { if (_gdbm_mapped_init (dbf) == 0) - dbf->mmap_inited = TRUE; + dbf->memory_mapping = TRUE; else { /* gdbm_errno should already be set. */ diff --git a/src/gdbmreorg.c b/src/gdbmreorg.c index aed372e..6bde222 100644 --- a/src/gdbmreorg.c +++ b/src/gdbmreorg.c @@ -176,7 +176,7 @@ gdbm_reorganize (GDBM_FILE dbf) } /* Re-initialize mapping if required */ - if (dbf->allow_mmap) + if (dbf->memory_mapping) _gdbm_mapped_init (dbf); dbf->desc = new_dbf->desc; diff --git a/src/gdbmsetopt.c b/src/gdbmsetopt.c index 54a972f..f9494d0 100644 --- a/src/gdbmsetopt.c +++ b/src/gdbmsetopt.c @@ -67,7 +67,9 @@ gdbm_setopt (GDBM_FILE dbf, int optflag, void *optval, int optlen) switch (optflag) { - case GDBM_CACHESIZE: + /* Cache size: */ + + case GDBM_SETCACHESIZE: /* Optval will point to the new size of the cache. */ if (dbf->bucket_cache != NULL) { @@ -79,34 +81,105 @@ gdbm_setopt (GDBM_FILE dbf, int optflag, void *optval, int optlen) return -1; return _gdbm_init_cache (dbf, (sz > 9) ? sz : 10); + case GDBM_GETCACHESIZE: + if (!optval || optlen != sizeof (size_t)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(size_t*) optval = dbf->cache_size; + break; + + /* Obsolete form of GDBM_SETSYNCMODE. */ case GDBM_FASTMODE: - /* Obsolete form of SYNCMODE. */ if ((n = getbool (optval, optlen)) == -1) return -1; dbf->fast_write = n; break; - - case GDBM_SYNCMODE: + + /* SYNC mode: */ + + case GDBM_SETSYNCMODE: /* Optval will point to either true or false. */ if ((n = getbool (optval, optlen)) == -1) return -1; dbf->fast_write = !n; break; - case GDBM_CENTFREE: + case GDBM_GETSYNCMODE: + if (!optval || optlen != sizeof (int)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(int*) optval = !dbf->fast_write; + break; + + /* CENTFREE - set or get the stat of the central block repository */ + case GDBM_SETCENTFREE: /* Optval will point to either true or false. */ if ((n = getbool (optval, optlen)) == -1) return -1; dbf->central_free = n; break; - case GDBM_COALESCEBLKS: + case GDBM_GETCENTFREE: + if (!optval || optlen != sizeof (int)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(int*) optval = !dbf->central_free; + break; + + /* Coalesce state: */ + case GDBM_SETCOALESCEBLKS: /* Optval will point to either true or false. */ if ((n = getbool (optval, optlen)) == -1) return -1; dbf->coalesce_blocks = n; break; + case GDBM_GETCOALESCEBLKS: + if (!optval || optlen != sizeof (int)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(int*) optval = dbf->coalesce_blocks; + break; + + /* Mmap mode */ + case GDBM_SETMMAP: + if ((n = getbool (optval, optlen)) == -1) + return -1; + __fsync (dbf); + if (n == dbf->memory_mapping) + return 0; + if (n) + { + if (_gdbm_mapped_init (dbf) == 0) + dbf->memory_mapping = TRUE; + else + return -1; + } + else + { + _gdbm_mapped_unmap (dbf); + dbf->memory_mapping = FALSE; + } + break; + + case GDBM_GETMMAP: + if (!optval || optlen != sizeof (int)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(int*) optval = dbf->memory_mapping; + break; + + /* Maximum size of a memory mapped region */ case GDBM_SETMAXMAPSIZE: { size_t page_size = sysconf (_SC_PAGESIZE); @@ -119,6 +192,35 @@ gdbm_setopt (GDBM_FILE dbf, int optflag, void *optval, int optlen) break; } + case GDBM_GETMAXMAPSIZE: + if (!optval || optlen != sizeof (size_t)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + *(size_t*) optval = dbf->mapped_size_max; + break; + + /* Flags */ + case GDBM_GETFLAGS: + if (!optval || optlen != sizeof (int)) + { + gdbm_errno = GDBM_OPT_ILLEGAL; + return -1; + } + else + { + int flags = dbf->read_write; + if (!dbf->fast_write) + flags |= GDBM_SYNC; + if (!dbf->file_locking) + flags |= GDBM_NOLOCK; + if (!dbf->memory_mapping) + flags |= GDBM_NOMMAP; + *(int*) optval = flags; + } + break; + default: gdbm_errno = GDBM_OPT_ILLEGAL; return -1; @@ -208,7 +208,7 @@ _gdbm_mapped_init (GDBM_FILE dbf) ssize_t _gdbm_mapped_read (GDBM_FILE dbf, void *buffer, size_t len) { - if (dbf->mmap_inited) + if (dbf->memory_mapping) { ssize_t total = 0; char *cbuf = buffer; @@ -225,7 +225,7 @@ _gdbm_mapped_read (GDBM_FILE dbf, void *buffer, size_t len) { int rc; - dbf->mmap_inited = FALSE; + dbf->memory_mapping = FALSE; if (lseek (dbf->desc, pos, SEEK_SET) != pos) return total > 0 ? total : -1; rc = read (dbf->desc, cbuf, len); @@ -258,7 +258,7 @@ _gdbm_mapped_read (GDBM_FILE dbf, void *buffer, size_t len) ssize_t _gdbm_mapped_write (GDBM_FILE dbf, void *buffer, size_t len) { - if (dbf->mmap_inited) + if (dbf->memory_mapping) { ssize_t total = 0; char *cbuf = buffer; @@ -275,7 +275,7 @@ _gdbm_mapped_write (GDBM_FILE dbf, void *buffer, size_t len) { int rc; - dbf->mmap_inited = FALSE; + dbf->memory_mapping = FALSE; if (lseek (dbf->desc, pos, SEEK_SET) != pos) return total > 0 ? total : -1; rc = write (dbf->desc, cbuf, len); @@ -312,7 +312,7 @@ _gdbm_mapped_write (GDBM_FILE dbf, void *buffer, size_t len) off_t _gdbm_mapped_lseek (GDBM_FILE dbf, off_t offset, int whence) { - if (dbf->mmap_inited) + if (dbf->memory_mapping) { off_t needle; |