Changes since last time:
* NO CHANGE IN APR_DBM.H (so no diffs ;))
* added licence file to dbm_private and put it in
private/apr_dbm_private.h
* GDBM is now there
* patch to apr_dbm.c.patch
* vtables are now static constants. (as per buckets)
* code style-cleanup to make it more apache. (might still be a stray
tab)
This version does NOT do:
* apr_dbm_open(XXX,...)
* apr_dbm_registration
* allow for multiple DBMs.
all it really does at the moment is split the file into 3 parts.
All it requires for existing 'users' of the DBM is a re-link to the new
library.
IF this patch is Ok, then I'll get the multi-dbm's working (which means
changing the configure, and adding the registeration/open(XXX))
XXX_Usednames is not part of the hook, as you don't need a DBM open to
call it. (and changing it to require it would break mod_dav, as it
doesn't seem to have a open DBM when it calls the funciton)
??comments???
Ian
On Wed, 2001-08-22 at 02:54, Greg Stein wrote:
> -1 until you put that GDBM support back in. It isn't right to just drop it.
>
> On Mon, Aug 20, 2001 at 04:50:25PM -0700, Ian Holsman wrote:
> > On Mon, 2001-08-20 at 13:07, Sterling Hughes wrote:
> >...
> > > Not sure I understand what you're saying? There are ways to allow
> > > the registering of module functionality, without modifying the main
> > > package. Just provide a function like:
> > >
> > > apr_dbm_register()
> > >
> > > Which registers a dbm internally, and then have a constant defined
> > > in a seperate file, and all is clear...
> > that would work,
> > but that wouldn't that mean there would be need to some init code
> > somewhere to call the registration function?
>
> Every time we load a module, we call registration functions. That is no big
> deal.
>
> Your solution of apr_dbm_*_open() still requires a recompilation/relink. The
> registration mechanism is completely open-ended.
>
> > > > 2. I may have a dbm which needs extra parameters to open it. (say for
> > > > exampe cache size, or maybe it requires
> > > > a fixed key length defined) I couldn't do this simply
> > > >
> > >
> > > dbm_set_x() and check the flags, once they're all filled out (a
> > > va_args implementation could also be done...)
>
> Not sure what you mean by dbm_set_x() here. You have to open the thing first
> to get an apr_dbm_t. But then you're too late.
>
> The va_arg solution is a semi-reasonable solution, but that kills any chance
> for type checking.
>
> > > Furthermore, the idea of an abstraction layer is too bring all these
> > > down to a lowest common denominator, at the cost of functionality
> > > sometimes; usually functions that take extra arguments, can be
> > > filled in with acceptable defaults. You'll run into the same
> > > problems in that some db's don't support certain features, and
> > > others do, the idea is to concentrate on the functionality that is
> > > necessary and shared between the different db's (wrap this in a
> > > large imho :).
>
> Exactly. apr_dbm exposes DBM-style functionality. Simple key/value pairs.
> That is it. The open functionality does not need flexibility. It has not
> been demonstrated yet that we need more capability there.
>
> > true, thats why they all return the same thing (apr_dbm_t)
> > the open_DBM function was supposed to be called when the devloper wanted
> > to do something specific with this type of dbm. so in the berkley DB
> > case there could be a apr_dbm_db_getRaw() function which returns the DB*
> > so that developers are not constrained the set of functions we chose to
> > abstract.
>
> No... we already have patterns for getting at underlying data types. See
> apr_portable.h. Follow that pattern *IF* we are to expose those. IMO, we
> should not do so.
>
> > (BTW I was planning on implmenting a shared-memory hash table, that I
> > posted ages ago, via this DBM interface, and it required a different set
> > of opening parameters (key/elem size, #elements) these parameters could
> > be passed via a db_set function call but it would look clunky
>
> No... keys and values are arbitrary length, as specified by an apr_datum_t.
> If your hash cannot handle that, then it cannot be used in the APR DBM
> interface.
>
> >...
> > so..
> > shall we put it to a vote?
> >
> > apr_dbm_open_XXX
> > or
> > apr_dbm_open(XXX)
>
> Registration and the second form.
>
>
> But your patch still has lots of work anyways. The GDBM functionality can't
> just disappear. Sorry, but the DAV functionality uses apr_dbm and you'd
> completely break access to the property files.
>
> Second, the vtable should not be part of the runtime apr_dbm_t structure.
> You should have a pointer to a static const table, like we do with buckets.
>
> The formatting may have gone thru "indent" but it still sucks. Just a glance
> over it shows some random gunk. For example, what the heck is up with the
> formatting of apr_datum_t in apr_dbm.h? And all the spacing of the function
> params in apr_dbm.h has been changed. There are extra blank lines at the end
> of some functions (after returns), and some missing blank lines between
> functions.
>
> We should also see a patch against apr_dbm.h, rather than the whole file. I
> can't see if you've changed the public interface or not.
>
> dbm_private.h is missing a license and disclaimer. It also has a
> non-standard #ifndef/#define/#endif pattern around it. We never start the
> symbol with "_", and on all the new .h files you specified: toss the "1"
> from the #define ... we don't do that either.
>
> Why is the "used names" functionality part of the per-db public interface?
> That should be part of the hook stuff just like the rest.
>
> In any case... the per-db headers should go, in favor of the registration
> mechanism. You would register each DB style with a name. You can then open a
> DB style by name, or using the reserved "any". Note that we would define
> some standard names:
>
> #define APR_DBM_USE_SDBM "sdbm"
> #define APR_DBM_USE_GDBM "gdbm"
> #define APR_DBM_USE_DB "db"
> #define APR_DBM_USE_ANY "any"
>
> Also, the whole point of this exercise was to link in all of the variations.
> That means the .c files should not have the #if APU_USE_*/#endif stuff
> around them. The APU_USE_* symbols are only used to determine which DB to
> use for the "any" case.
>
>
> So... -1 for now. The patch still needs work before it can be applied.
>
> Cheers,
> -g
>
--
Ian Holsman [EMAIL PROTECTED]
Performance Measurement & Analysis
CNET Networks - (415) 364-8608
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef APR_DBM_DB_H
#define APR_DBM_DB_H 1
#include "apr.h"
#include "apr_dbm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Open a Berkley DB file by file name
* @param dbm The newly opened database
* @param name The dbm file name to open
* @param mode The flag value
* <PRE>
* APR_DBM_READONLY open for read-only access
* APR_DBM_READWRITE open for read-write access
* APR_DBM_RWCREATE open for r/w, create if needed
* </PRE>
* @param perm Permissions to apply to if created
* @param cntxt The pool to use when creating the dbm
*/
APU_DECLARE(apr_status_t) apr_dbm_open_db(apr_dbm_t ** dbm, const char *name,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t * cntxt);
/**
* If the specified file/path were passed to apr_dbm_open_db(), return the
* actual file/path names which would be (created and) used. At most, two
* files may be used; used2 may be NULL if only one file is used.
* @param pool The pool for allocating used1 and used2.
* @param pathname The path name to generate used-names from.
* @param used1 The first pathname used by the apr_dbm implementation.
* @param used2 The second pathname used by apr_dbm. If only one file is
* used by the specific implementation, this will be set to NULL.
*/
APU_DECLARE(void) apr_dbm_get_usednames_db(apr_pool_t * p,
const char *pathname,
const char **used1,
const char **used2);
#ifdef __cplusplus
}
#endif
#endif /* !APR_DBM_DB_H */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef APR_DBM_GDBM_H
#define APR_DBM_GDBM_H 1
#include "apr.h"
#include "apr_dbm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Open a GDBM DB file by file name
* @param dbm The newly opened database
* @param name The dbm file name to open
* @param mode The flag value
* <PRE>
* APR_DBM_READONLY open for read-only access
* APR_DBM_READWRITE open for read-write access
* APR_DBM_RWCREATE open for r/w, create if needed
* </PRE>
* @param perm Permissions to apply to if created
* @param cntxt The pool to use when creating the dbm
*/
APU_DECLARE(apr_status_t) apr_dbm_open_gdbm(apr_dbm_t ** dbm, const char *name,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t * cntxt);
/**
* If the specified file/path were passed to apr_dbm_open_db(), return the
* actual file/path names which would be (created and) used. At most, two
* files may be used; used2 may be NULL if only one file is used.
* @param pool The pool for allocating used1 and used2.
* @param pathname The path name to generate used-names from.
* @param used1 The first pathname used by the apr_dbm implementation.
* @param used2 The second pathname used by apr_dbm. If only one file is
* used by the specific implementation, this will be set to NULL.
*/
APU_DECLARE(void) apr_dbm_get_usednames_gdbm(apr_pool_t * p,
const char *pathname,
const char **used1,
const char **used2);
#ifdef __cplusplus
}
#endif
#endif /* !APR_DBM_GDBM_H */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef APR_DBM_SDBM_H
#define APR_DBM_SDBM_H 1
#include "apr.h"
#include "apr_dbm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Open a SDBM file by file name
* @param dbm The newly opened database
* @param name The dbm file name to open
* @param mode The flag value
* <PRE>
* APR_DBM_READONLY open for read-only access
* APR_DBM_READWRITE open for read-write access
* APR_DBM_RWCREATE open for r/w, create if needed
* </PRE>
* @param perm Permissions to apply to if created
* @param cntxt The pool to use when creating the dbm
* @remark The dbm name may not be a true file name, as many dbm packages
* append suffixes for seperate data and index files.
*/
APU_DECLARE(apr_status_t) apr_dbm_open_sdbm(apr_dbm_t ** dbm, const char *name,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t * cntxt);
/**
* If the specified file/path were passed to apr_dbm_open_sdbm(), return the
* actual file/path names which would be (created and) used. At most, two
* files may be used; used2 may be NULL if only one file is used.
* @param pool The pool for allocating used1 and used2.
* @param pathname The path name to generate used-names from.
* @param used1 The first pathname used by the apr_dbm implementation.
* @param used2 The second pathname used by apr_dbm. If only one file is
* used by the specific implementation, this will be set to NULL.
*/
APU_DECLARE(void) apr_dbm_get_usednames_sdbm(apr_pool_t * p,
const char *pathname,
const char **used1,
const char **used2);
#ifdef __cplusplus
}
#endif
#endif /* !APR_DBM_SDBM_H */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef APR_DBM_PRIVATE_H
#define APR_DBM_PRIVATE_H 1
#ifdef __cplusplus
extern "C" {
#endif
/** @internal */
/**
* Most DBM libraries take a POSIX mode for creating files. Don't trust
* the mode_t type, some platforms may not support it, int is safe.
*/
APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm);
/**
* Structure to describe the operations of the DBM
*/
typedef struct {
/** The name of the DBM Type */
const char *name;
/** Set the error return code */
apr_status_t (*set_error) (apr_dbm_t * dbm, apr_status_t dbm_said);
/** Close the DBM */
void (*close) (apr_dbm_t * dbm);
/** Fetch a dbm record value by key */
apr_status_t (*fetch) (apr_dbm_t * dbm, apr_datum_t key,
apr_datum_t * pvalue);
/** Store a dbm record value by key */
apr_status_t (*store) (apr_dbm_t * dbm, apr_datum_t key,
apr_datum_t value);
/** Delete a dbm record value by key */
apr_status_t (*del) (apr_dbm_t * dbm, apr_datum_t key);
/** Search for a key within the dbm */
int (*exists) (apr_dbm_t * dbm, apr_datum_t key);
/** Retrieve the first record key from a dbm */
apr_status_t (*firstkey) (apr_dbm_t * dbm, apr_datum_t * pkey);
/** Retrieve the next record key from a dbm */
apr_status_t (*nextkey) (apr_dbm_t * dbm, apr_datum_t * pkey);
/** Report more information when an apr_dbm function fails. */
char * (*geterror) (apr_dbm_t * dbm, int *errcode, char *errbuf,
apr_size_t errbufsize);
/** if a DBM needs to call something free data */
apr_status_t (*datum_cleanup) (void *);
/** Proactively toss any memory associated with the apr_datum_t. */
void (*freedatum) (apr_dbm_t * dbm, apr_datum_t data);
} apr_dbm_type_t;
/**
* The actual DBM
*/
struct apr_dbm_t
{
apr_pool_t *pool;
/** pointer to DB Implementation Specific data */
void *file;
int errcode;
const char *errmsg;
/** the type of DBM */
const apr_dbm_type_t *type;
};
#ifdef __cplusplus
}
#endif
#endif /* !APR_DBM_PRIVATE_H */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apu_select_dbm.h"
#include "apr_dbm.h"
#if APU_USE_DB
#include "private/apr_dbm_private.h"
#include "apr_dbm_db.h"
#include <db.h>
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_db_t;
/*
* We pick up all varieties of Berkeley DB through db.h (included through
* apu_select_dbm.h). This code has been compiled/tested against DB1,
* DB_185, DB2, and DB3.
*/
#if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
#define DB_VER 3
#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
#define DB_VER 2
#else
#define DB_VER 1
#endif
typedef struct {
DB *bdb;
#if DB_VER != 1
DBC *curs;
#endif
} apr_berkeley_db_t;
#if DB_VER == 1
#include <sys/fcntl.h>
#define APR_DBM_DBMODE_RO O_RDONLY
#define APR_DBM_DBMODE_RW O_RDWR
#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
#else
#define APR_DBM_DBMODE_RO DB_RDONLY
#define APR_DBM_DBMODE_RW 0
#define APR_DBM_DBMODE_RWCREATE DB_CREATE
#endif
/* map a DB error to an apr_status_t */
static apr_status_t db2s(int dberr)
{
if (dberr != 0) {
return APR_OS_START_USEERR + dberr;
}
return APR_SUCCESS;
}
/* handle the FIRSTKEY functionality */
static apr_status_t do_firstkey(apr_berkeley_db_t * f, DBT * pkey)
{
int dberr;
DBT data;
memset(&data, 0, sizeof(DBT));
#if DB_VER == 1
dberr = (*f->bdb->seq)(f->bdb, pkey, &data, R_FIRST);
#else
/* DB_VER 1 doesn't do cursors */
#if DB_VER == 2
dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs);
#else
dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs , 0);
#endif /* DB_VER == 2 */
if (dberr == 0) {
dberr = (*f->curs->c_get)(f->curs, pkey, &data, DB_FIRST);
if (dberr == DB_NOTFOUND) {
memset(pkey, 0, sizeof(*pkey));
(*f->curs->c_close)(f->curs);
f->curs = NULL;
return APR_SUCCESS;
}
}
#endif /* DB_VER == 1 */
return db2s(dberr);
}
/*
* handle the NEXTKEY functionality
* This function also returns the 'data'
* as well as the key.
*/
static apr_status_t do_nextkey(apr_berkeley_db_t *f, DBT *pkey, DBT *pdata)
{
int dberr;
memset(pdata, 0, sizeof(DBT));
#if DB_VER == 1
dberr = (*f->bdb->seq)(f->bdb, pkey, pdata, R_NEXT);
#else
if (f->curs == NULL)
return APR_EINVAL;
dberr = (*f->curs->c_get)(f->curs, pkey, pdata, DB_NEXT);
if (dberr == DB_NOTFOUND) {
memset(pkey, 0, sizeof(*pkey));
memset(pdata, 0, sizeof(*pdata));
(*f->curs->c_close)(f->curs);
f->curs = NULL;
return APR_SUCCESS;
}
#endif /* DB_VER == 1 */
return db2s(dberr);
}
static apr_status_t apr_dbm_set_error_db(apr_dbm_t *dbm, apr_status_t dbm_said)
{
apr_status_t rv = APR_SUCCESS;
/* FIXME: check for error codes that APR already has and map the DB ones to them */
if (dbm_said == APR_SUCCESS) {
dbm->errcode = 0;
dbm->errmsg = NULL;
}
else {
dbm->errcode = dbm_said;
dbm->errmsg = db_strerror(dbm_said - APR_OS_START_USEERR);
rv = dbm_said;
}
return rv;
}
static void apr_dbm_close_db(apr_dbm_t *dbm)
{
apr_berkeley_db_t *real_ptr;
DB *db;
real_ptr = dbm->file;
if (real_ptr->bdb) {
db = real_ptr->bdb;
#if DB_VER == 1
db->close(db);
#else
db->close(db, 0);
#endif
// real_ptr->bdb=NULL;
}
}
/* make sure we clean up and close things */
static apr_status_t db_cleanup(void *p)
{
apr_dbm_t **db = p;
if (*db) {
apr_dbm_close_db(*db);
*db = NULL;
}
return APR_SUCCESS;
}
static apr_status_t apr_dbm_fetch_db(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t *pvalue)
{
apr_status_t rv;
apr_berkeley_db_t *real_ptr = dbm->file;
DB *db = real_ptr->bdb;
DBT ckey;
DBT rd;
int dberr;
memset(&ckey, 0, sizeof(DBT));
memset(&rd, 0, sizeof(DBT));
ckey.data = key.dptr;
ckey.size = key.dsize;
#if DB_VER == 1
dberr = db->get(db, &ckey, &rd, 0);
#else
dberr = db->get(db, NULL, &ckey, &rd, 0);
#endif
rv = db2s(dberr);
pvalue->dptr = rd.data;
pvalue->dsize = rd.size;
/*
* store the error info into DBM, and return a status code. Also, note
* that *pvalue should have been cleared on error.
*/
return apr_dbm_set_error_db(dbm, rv);
}
static apr_status_t apr_dbm_store_db(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t value)
{
apr_status_t rv;
int dberr;
apr_berkeley_db_t *real_ptr = dbm->file;
DB *db = real_ptr->bdb;
DBT ckey;
DBT cvalue;
memset(&ckey, 0, sizeof(DBT));
ckey.data = key.dptr;
ckey.size = key.dsize;
memset(&cvalue, 0, sizeof(DBT));
cvalue.data = value.dptr;
cvalue.size = value.dsize;
#if DB_VER == 1
dberr = db->put(db, &ckey, &cvalue, 0);
#else
dberr = db->put(db, NULL, &ckey, &cvalue, 0);
#endif
rv = db2s(dberr);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_db(dbm, rv);
}
static apr_status_t apr_dbm_delete_db(apr_dbm_t *dbm, apr_datum_t key)
{
apr_status_t rv;
DBT ckey;
apr_berkeley_db_t *real_ptr = dbm->file;
DB *db = real_ptr->bdb;
int dberr;
memset(&ckey, 0, sizeof(DBT));
ckey.data = key.dptr;
ckey.size = key.dsize;
#if DB_VER ==1
dberr = db->del(db, &ckey, 0);
#else
dberr = db->del(db, NULL, &ckey, 0);
#endif
rv = db2s(dberr);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_db(dbm, rv);
}
static int apr_dbm_exists_db(apr_dbm_t *dbm, apr_datum_t key)
{
int exists;
DBT ckey;
DBT data;
apr_berkeley_db_t *real_ptr = dbm->file;
DB *db = real_ptr->bdb;
int dberr;
memset(&ckey, 0, sizeof(DBT));
ckey.data = key.dptr;
ckey.size = key.dsize;
memset(&data, 0, sizeof(DBT));
data.data = key.dptr;
data.size = key.dsize;
#if DB_VER ==1
dberr = db->get(db, &ckey, &data, 0);
#else
dberr = db->get(db, NULL, &ckey, &data, 0);
#endif
/*
* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
* that *any* error means it doesn't exist.
*/
exists = dberr == 0;
return exists;
}
static apr_status_t apr_dbm_firstkey_db(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
DBT rd;
apr_berkeley_db_t *real_ptr = dbm->file;
memset(&rd, 0, sizeof(DBT));
rv = do_firstkey(real_ptr, &rd);
pkey->dptr = rd.data;
pkey->dsize = rd.size;
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_db(dbm, rv);
}
static apr_status_t apr_dbm_nextkey_db(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
DBT ckey;
DBT rd;
apr_berkeley_db_t *real_ptr = dbm->file;
memset(&rd, 0, sizeof(DBT));
memset(&ckey, 0, sizeof(DBT));
ckey.data = pkey->dptr;
ckey.size = pkey->dsize;
rv = do_nextkey(real_ptr, &ckey, &rd);
pkey->dptr = ckey.data;
pkey->dsize = ckey.size;
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_db(dbm, APR_SUCCESS);
}
static void apr_dbm_freedatum_noop(apr_dbm_t *dbm, apr_datum_t data)
{
/* do nothing */
}
static apr_status_t apr_dbm_datum_cleanup_noop(void *x)
{
return APR_SUCCESS;
}
static char *apr_dbm_geterror_db(apr_dbm_t *dbm, int *errcode,
char *errbuf, apr_size_t errbufsize)
{
if (errcode != NULL) {
*errcode = dbm->errcode;
}
if (dbm->errmsg == NULL) {
*errbuf = '\0';
}
else {
(void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
}
return errbuf;
}
APU_DECLARE(void) apr_dbm_get_usednames_db(apr_pool_t *p,
const char *pathname,
const char **used1,
const char **used2)
{
*used1 = apr_pstrdup(p, pathname);
*used2 = NULL;
}
APU_DECLARE(apr_status_t) apr_dbm_open_db(apr_dbm_t **pdb,
const char *pathname,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t *pool)
{
apr_berkeley_db_t *file = apr_pcalloc(pool, sizeof(apr_berkeley_db_t));
int dbmode;
int dberr;
*pdb = NULL;
switch (mode) {
case APR_DBM_READONLY:
dbmode = APR_DBM_DBMODE_RO;
break;
case APR_DBM_READWRITE:
dbmode = APR_DBM_DBMODE_RW;
break;
case APR_DBM_RWCREATE:
dbmode = APR_DBM_DBMODE_RWCREATE;
break;
default:
return APR_EINVAL;
}
/*
* Allocate the structure before attempting to open
* the DB.
* (so we can call a error routine if we fail to open)
*/
*pdb = apr_pcalloc(pool, sizeof(**pdb));
(*pdb)->pool = pool;
(*pdb)->file = file;
(*pdb)->type = &apr_dbm_type_db_t;
#if DB_VER == 3
if ((dberr = db_create(&file->bdb, NULL, 0)) == 0) {
if ((dberr = (*file->bdb->open)(file->bdb, pathname, NULL, DB_HASH,
dbmode,
apr_posix_perms2mode(perm))) != 0) {
/* close the DB handler */
(void)(*file->bdb->close)(file->bdb, 0);
}
}
file->curs = NULL;
#elif DB_VER == 2
dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
NULL, NULL, &file->bdb);
file->curs = NULL;
#else
file->bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
DB_HASH, NULL);
if (file->bdb == NULL)
return APR_OS_START_USEERR; /* ### need a better error */
dberr = 0;
#endif
if (dberr != 0)
return apr_dbm_set_error_db(*pdb, db2s(dberr));
/* FIXME:
* My thinking here is that we should register a cleanup to close the DBM.
* This should be done as BerkleyDB caches stuff and really needs to be
* closed down properly.
*
* but the current code doesn't do this, and the other DBMs don't do it eiher.
* (and it segfaults ;( )
* maybe pool is deleted before this is ??run??
* apr_pool_cleanup_register(pool, pdb, db_cleanup,apr_pool_cleanup_null);
*/
return APR_SUCCESS;
}
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_db_t= {
"DB",
apr_dbm_set_error_db,
apr_dbm_close_db,
apr_dbm_fetch_db,
apr_dbm_store_db,
apr_dbm_delete_db,
apr_dbm_exists_db,
apr_dbm_firstkey_db,
apr_dbm_nextkey_db,
apr_dbm_geterror_db,
apr_dbm_datum_cleanup_noop,
apr_dbm_freedatum_noop
};
#endif /* !APU_USE_DB */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apu_select_dbm.h"
#include "apr_dbm.h"
#if APU_USE_GDBM
#include "private/apr_dbm_private.h"
#include "apr_dbm_gdbm.h"
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm_t;
#include <gdbm.h>
#include <stdlib.h> /* for free() */
#define APR_DBM_DBMODE_RO GDBM_READER
#define APR_DBM_DBMODE_RW GDBM_WRITER
#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
/* map a GDBM error to an apr_status_t */
static apr_status_t g2s(int gerr)
{
if (gerr == -1) {
return APR_OS_START_USEERR+gerr;
}
return APR_SUCCESS;
}
static apr_status_t datum_cleanup(void *dptr)
{
if (dptr)
free(dptr);
return APR_SUCCESS;
}
#define REGISTER_CLEANUP(dbm, pdatum) \
if ((pdatum)->dptr) \
apr_pool_cleanup_register((dbm)->pool, (pdatum)->dptr, \
datum_cleanup, apr_pool_cleanup_null); \
else
static apr_status_t apr_dbm_set_error_gdbm(apr_dbm_t *dbm, apr_status_t dbm_said)
{
apr_status_t rv = APR_SUCCESS;
/* FIXME: check for error codes that APR already has and map the DB ones to them */
if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
dbm->errmsg = NULL;
}
else {
dbm->errmsg = gdbm_strerror(gdbm_errno);
rv = APR_OS_START_USEERR+gdbm_errno;
}
/* captured it. clear it now. */
gdbm_errno = GDBM_NO_ERROR;
return rv;
}
static void apr_dbm_close_gdbm(apr_dbm_t *dbm)
{
gdbm_close(f)
}
static apr_status_t apr_dbm_fetch_gdbm(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t *pvalue)
{
apr_status_t rv;
datum* ckey;
datum rd;
ckey = (datum *)&key;
rd = gdbm_fetch(dbm->file,*ckey);
*pvalue = *(apr_datum_t *)&(rd);
REGISTER_CLEANUP(dbm, pvalue);
/* XXX: gdbm_fetch doesn't return an error code?? */
return apr_dbm_set_error_gdbm(dbm, APR_SUCCESS);
}
static apr_status_t apr_dbm_store_gdbm(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t value)
{
apr_status_t rv;
int gret;
datum *ckey;
datum *cvalue;
ckey = (datum *)&key;
cvalue = (datum *)&value;
gret = gdbm_store(dbm->file, *ckey,*cvalue, GDBM_REPLACE);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_gdbm(dbm, g2s(gret) );
}
static apr_status_t apr_dbm_delete_gdbm(apr_dbm_t *dbm, apr_datum_t key)
{
apr_status_t rv;
datum* ckey;
int gret;
ckey = (datum *)&key;
gret = gdbm_delete(dbm->file, *ckey);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_gdbm(dbm, g2s(gret));
}
static int apr_dbm_exists_gdbm(apr_dbm_t *dbm, apr_datum_t key)
{
int exists;
datum *ckey;
ckey = (datum *)&key;
exists = gdbm_exists(dbm->file, *ckey) != 0;
return exists;
}
static apr_status_t apr_dbm_firstkey_gdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
datum rd;
rd = gdbm_firstkey(dbm->file);
*pkey = *(apr_datum_t *)&(rd);
REGISTER_CLEANUP(dbm, pkey);
/* store any error info into DBM, and return a status code. */
/** XXX: gdbm doesn't return a error?? */
return apr_dbm_set_error_gdbm(dbm, APR_SUCCESS);
}
static apr_status_t apr_dbm_nextkey_gdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
datum *ckey;
datum rd;
ckey = (datum *)pkey;
rv = APR_DBM_NEXTKEY(dbm->file, ckey, rd);
*pkey = *(apr_datum_t *)&(rd);
rd = gdbm_nextkey(dbm->file, *ckey);
REGISTER_CLEANUP(dbm, pkey);
/* store any error info into DBM, and return a status code. */
/** XXX: gdbm doesn't return a error?? */
return apr_dbm_set_error_gdbm(dbm, APR_SUCCESS);
}
static void apr_dbm_freedatum_gdbm(apr_dbm_t *dbm, apr_datum_t data)
{
(void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
}
static char *apr_dbm_geterror_gdbm(apr_dbm_t *dbm, int *errcode, char *errbuf,
apr_size_t errbufsize)
{
if (errcode != NULL)
*errcode = dbm->errcode;
if (dbm->errmsg == NULL)
*errbuf = '\0';
else
(void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
return errbuf;
}
APU_DECLARE(void) apr_dbm_get_usednames_gdbm(apr_pool_t *p,
const char *pathname,
const char **used1,
const char **used2)
{
*used1 = apr_pstrdup(p, pathname);
*used2 = NULL;
}
APU_DECLARE(apr_status_t) apr_dbm_open_gdbm(apr_dbm_t **pdb,
const char *pathname,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t *pool)
{
int dbmode;
int dberr;
*pdb = NULL;
switch (mode) {
case APR_DBM_READONLY:
dbmode = APR_DBM_DBMODE_RO;
break;
case APR_DBM_READWRITE:
dbmode = APR_DBM_DBMODE_RW;
break;
case APR_DBM_RWCREATE:
dbmode = APR_DBM_DBMODE_RWCREATE;
break;
default:
return APR_EINVAL;
}
/*
* Allocate the structure before attempting to open
* the DB.
* (so we can call a error routine if we fail to open)
*/
*pdb = apr_pcalloc(pool, sizeof(**pdb));
(*pdb)->pool = pool;
(*pdb)->type = &apr_dbm_type_gdbm_t;
(*pdb)->file = gdbm_open((char *) pathname, 0, dbmode,
apr_posix_perms2mode(perm), NULL);
if ((*pdb)->file == NULL)
return APR_EGENERAL; /* ### need a better error */
return APR_SUCCESS;
}
static apr_status_t apr_dbm_datum_cleanup_gdbm(void *dptr)
{
if (dptr)
free(dptr);
return APR_SUCCESS;
}
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm_t= {
"GDBM",
apr_dbm_set_error_gdbm,
apr_dbm_close_gdbm,
apr_dbm_fetch_gdbm,
apr_dbm_store_gdbm,
apr_dbm_delete_gdbm,
apr_dbm_exists_gdbm,
apr_dbm_firstkey_gdbm,
apr_dbm_nextkey_gdbm,
apr_dbm_geterror_gdbm,
apr_dbm_datum_cleanup_gdbm,
apr_dbm_freedatum_gdbm
};
#endif /* !APU_USE_GDBM */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apu_select_dbm.h"
#include "apr_dbm.h"
#include "apu.h"
#if APU_USE_SDBM
#include "private/apr_dbm_private.h"
#include "apr_dbm_sdbm.h"
#include "apr_sdbm.h"
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_sdbm_t;
#define APR_DBM_DBMODE_RO APR_READ
#define APR_DBM_DBMODE_RW (APR_READ | APR_WRITE)
#define APR_DBM_DBMODE_RWCREATE (APR_READ | APR_WRITE | APR_CREATE)
static void apr_dbm_close_sdbm(apr_dbm_t *dbm)
{
apr_sdbm_close((apr_sdbm_t *) dbm->file);
}
static apr_status_t apr_dbm_set_error_sdbm(apr_dbm_t *dbm,
apr_status_t dbm_said)
{
apr_status_t rv = APR_SUCCESS;
/* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
if ((dbm->errcode = dbm_said) == APR_SUCCESS) {
dbm->errmsg = NULL;
}
else {
dbm->errmsg = "I/O error occurred.";
/* XXX: SDBM returns APR Error codes*/
rv = dbm->errcode;
}
return rv;
}
static apr_status_t apr_dbm_fetch_sdbm(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t *pvalue)
{
apr_status_t rv;
apr_sdbm_datum_t *ckey;
apr_sdbm_datum_t rd;
ckey = (apr_sdbm_datum_t *) & key;
rd.dptr = NULL;
rd.dsize = -1;
rv = apr_sdbm_fetch(dbm->file, &rd, *ckey);
*(pvalue) = *(apr_datum_t *) & rd;
/* store the error info into DBM, and return a status code. Also, note
that *pvalue should have been cleared on error. */
return apr_dbm_set_error_sdbm(dbm, rv);
}
static apr_status_t apr_dbm_store_sdbm(apr_dbm_t *dbm, apr_datum_t key,
apr_datum_t value)
{
apr_status_t rv;
apr_sdbm_datum_t *ckey;
apr_sdbm_datum_t *cvalue;
ckey = (apr_sdbm_datum_t *) & key;
cvalue = (apr_sdbm_datum_t *) & value;
rv = apr_sdbm_store(dbm->file, *ckey, *cvalue, APR_SDBM_REPLACE);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_sdbm(dbm, rv);
}
static apr_status_t apr_dbm_delete_sdbm(apr_dbm_t *dbm, apr_datum_t key)
{
apr_status_t rv;
apr_sdbm_datum_t *ckey;
ckey = (apr_sdbm_datum_t *) & key;
rv = apr_sdbm_delete(dbm->file, *ckey);
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_sdbm(dbm, rv);
}
static int apr_dbm_exists_sdbm(apr_dbm_t *dbm, apr_datum_t key)
{
int exists;
apr_sdbm_datum_t *ckey;
apr_sdbm_datum_t value;
ckey = (apr_sdbm_datum_t *) & key;
if (apr_sdbm_fetch(dbm->file, &value, *ckey) != APR_SUCCESS) {
exists = 0;
}
else {
exists = value.dptr != NULL;
}
return exists;
}
static apr_status_t apr_dbm_firstkey_sdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
apr_sdbm_datum_t rd;
rv = apr_sdbm_firstkey(dbm->file, &rd);
*pkey = *(apr_datum_t *) & rd;
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_sdbm(dbm, rv);
}
static apr_status_t apr_dbm_nextkey_sdbm(apr_dbm_t *dbm, apr_datum_t *pkey)
{
apr_status_t rv;
apr_sdbm_datum_t *ckey;
apr_sdbm_datum_t rd;
ckey = (apr_sdbm_datum_t *) pkey;
rv = apr_sdbm_nextkey(dbm->file, &rd);
*pkey = *(apr_datum_t *) & rd;
/* store any error info into DBM, and return a status code. */
return apr_dbm_set_error_sdbm(dbm, APR_SUCCESS);
}
APU_DECLARE(void) apr_dbm_get_usednames_sdbm(apr_pool_t *p,
const char *pathname,
const char **used1,
const char **used2)
{
char *work;
*used1 = apr_pstrcat(p, pathname, APR_SDBM_DIRFEXT, NULL);
*used2 = work = apr_pstrdup(p, *used1);
/* we know the extension is 4 characters */
memcpy(&work[strlen(work) - 4], APR_SDBM_PAGFEXT, 4);
}
static void apr_dbm_freedatum_noop(apr_dbm_t *dbm, apr_datum_t data)
{
/* do nothing */
}
static apr_status_t apr_dbm_datum_cleanup_noop(void *x)
{
return APR_SUCCESS;
}
static char *apr_dbm_geterror_sdbm(apr_dbm_t *dbm, int *errcode, char *errbuf,
apr_size_t errbufsize)
{
if (errcode != NULL)
*errcode = dbm->errcode;
if (dbm->errmsg == NULL) {
*errbuf = '\0';
}
else {
(void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
}
return errbuf;
}
APU_DECLARE(apr_status_t) apr_dbm_open_sdbm(apr_dbm_t **pdb,
const char *pathname,
apr_int32_t mode,
apr_fileperms_t perm,
apr_pool_t *pool)
{
apr_sdbm_t *file;
apr_status_t rv;
int dbmode;
*pdb = NULL;
switch (mode) {
case APR_DBM_READONLY:
dbmode = APR_DBM_DBMODE_RO;
break;
case APR_DBM_READWRITE:
dbmode = APR_DBM_DBMODE_RW;
break;
case APR_DBM_RWCREATE:
dbmode = APR_DBM_DBMODE_RWCREATE;
break;
default:
return APR_EINVAL;
}
rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
if (rv != APR_SUCCESS)
return rv;
*pdb = apr_pcalloc(pool, sizeof(**pdb));
(*pdb)->pool = pool;
(*pdb)->file = file;
(*pdb)->type = &apr_dbm_type_sdbm_t;
/* we have an open database... return it */
return APR_SUCCESS;
}
APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_sdbm_t= {
"SDBM",
apr_dbm_set_error_sdbm,
apr_dbm_close_sdbm,
apr_dbm_fetch_sdbm,
apr_dbm_store_sdbm,
apr_dbm_delete_sdbm,
apr_dbm_exists_sdbm,
apr_dbm_firstkey_sdbm,
apr_dbm_nextkey_sdbm,
apr_dbm_geterror_sdbm,
apr_dbm_datum_cleanup_noop,
apr_dbm_freedatum_noop
};
#endif /* !APU_USE_SDBM */
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
#ifdef APR_HAVE_STDIO_H
#include <stdio.h>
#endif
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apu_select_dbm.h"
#include "apr_dbm.h"
#include "private/apr_dbm_private.h"
/* this is so we can select a 'default' open/getnames */
#if APU_USE_SDBM
#include "apr_dbm_sdbm.h"
#elif APU_USE_DB
#include "apr_dbm_db.h"
#elif APU_USE_GDBM
#include "apr_dbm_gdbm.h"
#endif
/* Most DBM libraries take a POSIX mode for creating files. Don't trust
* the mode_t type, some platforms may not support it, int is safe.
*/
APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
{
int mode = 0;
mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */
mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
mode |= 0007 & (perm); /* World maps 1 for 1 */
return mode;
}
APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t ** pdb, const char *pathname,
apr_int32_t mode, apr_fileperms_t perm,
apr_pool_t * pool)
{
#if APU_USE_SDBM
return apr_dbm_open_sdbm(pdb, pathname, mode, perm, pool);
#elif APU_USE_DB
return apr_dbm_open_db(pdb, pathname, mode, perm, pool);
#elif APU_USE_GDBM
return apr_dbm_open_gdbm(pdb, pathname, mode, perm, pool);
#else
return APR_ENOTAVAIL;
#endif
}
APU_DECLARE(void) apr_dbm_close(apr_dbm_t * dbm)
{
dbm->type->close(dbm);
}
APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t * dbm, apr_datum_t key,
apr_datum_t * pvalue)
{
return dbm->type->fetch(dbm, key, pvalue);
}
APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t * dbm, apr_datum_t key,
apr_datum_t value)
{
return dbm->type->store(dbm, key, value);
}
APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t * dbm, apr_datum_t key)
{
return dbm->type->del(dbm, key);
}
APU_DECLARE(int) apr_dbm_exists(apr_dbm_t * dbm, apr_datum_t key)
{
return dbm->type->exists(dbm, key);
}
APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t * dbm,
apr_datum_t * pkey)
{
return dbm->type->firstkey(dbm, pkey);
}
APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t * dbm, apr_datum_t * pkey)
{
return dbm->type->nextkey(dbm, pkey);
}
APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t * dbm, apr_datum_t data)
{
dbm->type->freedatum(dbm, data);
}
APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t * dbm, int *errcode,
char *errbuf, apr_size_t errbufsize)
{
return dbm->type->geterror(dbm, errcode, errbuf, errbufsize);
}
APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t * p,
const char *pathname,
const char **used1,
const char **used2)
{
#if APU_USE_SDBM
apr_dbm_get_usednames_sdbm(p, pathname, used1, used2);
#elif APU_USE_DB
apr_dbm_get_usednames_db(p, pathname, used1, used2);
#elif APU_USE_GDBM
apr_dbm_get_usednames_gdbm(p, pathname, used1, used2);
#else
/* default op. no assumptions made */
fprintf(stderr, "This Database does not implement apr_dbm_get_usednames");
*used1 = NULL;
*used2 = NULL;
#endif
}
Index: apr_dbm.c
===================================================================
RCS file: /home/cvs/apr-util/dbm/apr_dbm.c,v
retrieving revision 1.26
diff -u -u -r1.26 apr_dbm.c
--- apr_dbm.c 2001/05/21 19:14:39 1.26
+++ apr_dbm.c 2001/08/24 18:31:40
@@ -56,49 +56,30 @@
#include "apr_errno.h"
#include "apr_pools.h"
#include "apr_strings.h"
+#ifdef APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apu_select_dbm.h"
#include "apr_dbm.h"
-
-
-/* this is used in a few places to define a noop "function". it is needed
- to stop "no effect" warnings from GCC. */
-#define NOOP_FUNCTION if (0) ; else
+#include "private/apr_dbm_private.h"
-
+/* this is so we can select a 'default' open/getnames */
#if APU_USE_SDBM
-
-#include "apr_sdbm.h"
-
-typedef apr_sdbm_t *real_file_t;
-
-typedef apr_sdbm_datum_t *cvt_datum_t;
-#define CONVERT_DATUM(cvt, pinput) ((cvt) = (apr_sdbm_datum_t *)(pinput))
-
-typedef apr_sdbm_datum_t result_datum_t;
-#define RETURN_DATUM(poutput, rd) (*(poutput) = *(apr_datum_t *)&(rd))
-
-#define APR_DBM_CLOSE(f) apr_sdbm_close(f)
-#define APR_DBM_FETCH(f, k, v) apr_sdbm_fetch(f, &(v), *(k))
-#define APR_DBM_STORE(f, k, v) apr_sdbm_store(f, *(k), *(v), APR_SDBM_REPLACE)
-#define APR_DBM_DELETE(f, k) apr_sdbm_delete(f, *(k))
-#define APR_DBM_FIRSTKEY(f, k) apr_sdbm_firstkey(f, &(k))
-#define APR_DBM_NEXTKEY(f, k, nk) apr_sdbm_nextkey(f, &(nk))
-#define APR_DBM_FREEDPTR(dptr) NOOP_FUNCTION
-
-#define APR_DBM_DBMODE_RO APR_READ
-#define APR_DBM_DBMODE_RW (APR_READ | APR_WRITE)
-#define APR_DBM_DBMODE_RWCREATE (APR_READ | APR_WRITE | APR_CREATE)
-
-#else /* Not using SDBM: */
+#include "apr_dbm_sdbm.h"
+#elif APU_USE_DB
+#include "apr_dbm_db.h"
+#elif APU_USE_GDBM
+#include "apr_dbm_gdbm.h"
+#endif
/* Most DBM libraries take a POSIX mode for creating files. Don't trust
* the mode_t type, some platforms may not support it, int is safe.
*/
-int apr_posix_perms2mode(apr_fileperms_t perm)
+APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
{
int mode = 0;
@@ -108,494 +89,88 @@
return mode;
}
-#if APU_USE_GDBM
-
-#include <gdbm.h>
-#include <stdlib.h> /* for free() */
-
-typedef GDBM_FILE real_file_t;
-
-typedef datum *cvt_datum_t;
-#define CONVERT_DATUM(cvt, pinput) ((cvt) = (datum *)(pinput))
-
-typedef datum result_datum_t;
-#define RETURN_DATUM(poutput, rd) (*(poutput) = *(apr_datum_t *)&(rd))
-
-#define APR_DBM_CLOSE(f) gdbm_close(f)
-#define APR_DBM_FETCH(f, k, v) ((v) = gdbm_fetch(f, *(k)), APR_SUCCESS)
-#define APR_DBM_STORE(f, k, v) g2s(gdbm_store(f, *(k), *(v), GDBM_REPLACE))
-#define APR_DBM_DELETE(f, k) g2s(gdbm_delete(f, *(k)))
-#define APR_DBM_FIRSTKEY(f, k) ((k) = gdbm_firstkey(f), APR_SUCCESS)
-#define APR_DBM_NEXTKEY(f, k, nk) ((nk) = gdbm_nextkey(f, *(k)), APR_SUCCESS)
-#define APR_DBM_FREEDPTR(dptr) ((dptr) ? free(dptr) : 0)
-
-#define NEEDS_CLEANUP
-
-#define APR_DBM_DBMODE_RO GDBM_READER
-#define APR_DBM_DBMODE_RW GDBM_WRITER
-#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
-
-/* map a GDBM error to an apr_status_t */
-static apr_status_t g2s(int gerr)
-{
- if (gerr == -1) {
- /* ### need to fix this */
- return APR_EGENERAL;
- }
-
- return APR_SUCCESS;
-}
-
-#elif APU_USE_DB
-/*
- * We pick up all varieties of Berkeley DB through db.h (included through
- * apu_select_dbm.h). This code has been compiled/tested against DB1,
- * DB_185, DB2, and DB3.
- */
-
-#if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
-#define DB_VER 3
-#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
-#define DB_VER 2
-#else
-#define DB_VER 1
-#endif
-
-typedef struct {
- DB *bdb;
-#if DB_VER != 1
- DBC *curs;
-#endif
-} real_file_t;
-
-typedef DBT cvt_datum_t;
-#define CONVERT_DATUM(cvt, pinput) (memset(&(cvt), 0, sizeof(cvt)), \
- (cvt).data = (pinput)->dptr, \
- (cvt).size = (pinput)->dsize)
-
-typedef DBT result_datum_t;
-#define RETURN_DATUM(poutput, rd) ((poutput)->dptr = (rd).data, \
- (poutput)->dsize = (rd).size)
-
-#if DB_VER == 1
-#define TXN_ARG
-#else
-#define TXN_ARG NULL,
-#endif
-
-#if DB_VER == 1
-#define APR_DBM_CLOSE(f) ((*(f).bdb->close)((f).bdb))
-#else
-#define APR_DBM_CLOSE(f) ((*(f).bdb->close)((f).bdb, 0))
-#endif
-
-#define do_fetch(f, k, v) ((*(f)->get)(f, TXN_ARG &(k), &(v), 0))
-#define APR_DBM_FETCH(f, k, v) db2s(do_fetch((f).bdb, k, v))
-#define APR_DBM_STORE(f, k, v) db2s((*(f).bdb->put)((f).bdb, TXN_ARG &(k),
&(v), 0))
-#define APR_DBM_DELETE(f, k) db2s((*(f).bdb->del)((f).bdb, TXN_ARG &(k), 0))
-#define APR_DBM_FIRSTKEY(f, k) do_firstkey(&(f), &(k))
-#define APR_DBM_NEXTKEY(f, k, nk) do_nextkey(&(f), &(k), &(nk))
-#define APR_DBM_FREEDPTR(dptr) NOOP_FUNCTION
-
-#if DB_VER == 1
-#include <sys/fcntl.h>
-#define APR_DBM_DBMODE_RO O_RDONLY
-#define APR_DBM_DBMODE_RW O_RDWR
-#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
-#else
-#define APR_DBM_DBMODE_RO DB_RDONLY
-#define APR_DBM_DBMODE_RW 0
-#define APR_DBM_DBMODE_RWCREATE DB_CREATE
-#endif
-
-/* map a DB error to an apr_status_t */
-static apr_status_t db2s(int dberr)
-{
- if (dberr != 0) {
- /* ### need to fix this */
- return APR_EGENERAL;
- }
-
- return APR_SUCCESS;
-}
-
-/* handle the FIRSTKEY functionality */
-static apr_status_t do_firstkey(real_file_t *f, DBT *pkey)
-{
- int dberr;
- DBT data;
-
-#if DB_VER == 1
- dberr = (*f->bdb->seq)(f->bdb, pkey, &data, R_FIRST);
-#else
- if ((dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs
-#if DB_VER == 3
- , 0
-#endif
- )) == 0) {
- dberr = (*f->curs->c_get)(f->curs, pkey, &data, DB_FIRST);
- if (dberr == DB_NOTFOUND) {
- memset(pkey, 0, sizeof(*pkey));
- (*f->curs->c_close)(f->curs);
- f->curs = NULL;
- return APR_SUCCESS;
- }
- }
-#endif
-
- return db2s(dberr);
-}
-
-/* handle the NEXTKEY functionality */
-static apr_status_t do_nextkey(real_file_t *f, DBT *pkey, DBT *pnext)
-{
- int dberr;
- DBT data;
-
-#if DB_VER == 1
- dberr = (*f->bdb->seq)(f->bdb, pkey, &data, R_NEXT);
-#else
- if (f->curs == NULL)
- return APR_EINVAL;
-
- dberr = (*f->curs->c_get)(f->curs, pkey, &data, DB_NEXT);
- if (dberr == DB_NOTFOUND) {
- memset(pkey, 0, sizeof(*pkey));
- (*f->curs->c_close)(f->curs);
- f->curs = NULL;
- return APR_SUCCESS;
- }
-#endif
-
- return db2s(dberr);
-}
-
-#else /* Not in the USE_xDBM list above */
-#error a DBM implementation was not specified
-#endif
-
-#endif /* Not USE_SDBM */
-
-struct apr_dbm_t
-{
- apr_pool_t *pool;
- real_file_t file;
-
- int errcode;
- const char *errmsg;
-};
-
-
-#ifdef NEEDS_CLEANUP
-
-static apr_status_t datum_cleanup(void *dptr)
-{
- APR_DBM_FREEDPTR(dptr);
- return APR_SUCCESS;
-}
-
-#define REGISTER_CLEANUP(dbm, pdatum) \
- if ((pdatum)->dptr) \
- apr_pool_cleanup_register((dbm)->pool, (pdatum)->dptr, \
- datum_cleanup, apr_pool_cleanup_null); \
- else
-
-#else /* NEEDS_CLEANUP */
-
-#define REGISTER_CLEANUP(dbm, pdatum) NOOP_FUNCTION
-
-#endif /* NEEDS_CLEANUP */
-
-static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
-{
- apr_status_t rv = APR_SUCCESS;
-
- /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
-
-#if APU_USE_SDBM
-
- if ((dbm->errcode = dbm_said) == APR_SUCCESS) {
- dbm->errmsg = NULL;
- }
- else {
- dbm->errmsg = "I/O error occurred.";
- rv = APR_EGENERAL; /* ### need something better */
- }
-
-#elif APU_USE_GDBM
-
- if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
- dbm->errmsg = NULL;
- }
- else {
- dbm->errmsg = gdbm_strerror(gdbm_errno);
- rv = APR_EGENERAL; /* ### need something better */
- }
-
- /* captured it. clear it now. */
- gdbm_errno = GDBM_NO_ERROR;
-
-#elif APU_USE_DB
- if (dbm_said == APR_SUCCESS) {
- dbm->errcode = 0;
- dbm->errmsg = NULL;
- }
- else {
- /* ### need to fix. dberr was tossed in db2s(). */
- /* ### use db_strerror() */
- dbm->errcode = 1;
- dbm->errmsg = "DB error occurred.";
- rv = APR_EGENERAL;
- }
-#else
-#error set_error has not been coded for this database type
-#endif
-
- return rv;
-}
-APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname,
+APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t ** pdb, const char *pathname,
apr_int32_t mode, apr_fileperms_t perm,
- apr_pool_t *pool)
+ apr_pool_t * pool)
{
- real_file_t file;
- int dbmode;
-
- *pdb = NULL;
-
- switch (mode) {
- case APR_DBM_READONLY:
- dbmode = APR_DBM_DBMODE_RO;
- break;
- case APR_DBM_READWRITE:
- dbmode = APR_DBM_DBMODE_RW;
- break;
- case APR_DBM_RWCREATE:
- dbmode = APR_DBM_DBMODE_RWCREATE;
- break;
- default:
- return APR_EINVAL;
- }
-
#if APU_USE_SDBM
-
- {
- apr_status_t rv;
-
- rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
- if (rv != APR_SUCCESS)
- return rv;
- }
-
-#elif APU_USE_GDBM
-
- {
- /* Note: stupid cast to get rid of "const" on the pathname */
- file = gdbm_open((char *) pathname, 0, dbmode,
- apr_posix_perms2mode(perm), NULL);
- if (file == NULL)
- return APR_EGENERAL; /* ### need a better error */
- }
-
+ return apr_dbm_open_sdbm(pdb, pathname, mode, perm, pool);
#elif APU_USE_DB
-
- {
- int dberr;
-
-#if DB_VER == 3
- if ((dberr = db_create(&file.bdb, NULL, 0)) == 0) {
- if ((dberr = (*file.bdb->open)(file.bdb, pathname, NULL,
- DB_HASH, dbmode,
- apr_posix_perms2mode(perm))) != 0) {
- /* close the DB handler */
- (void) (*file.bdb->close)(file.bdb, 0);
- }
- }
- file.curs = NULL;
-#elif DB_VER == 2
- dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
- NULL, NULL, &file.bdb);
- file.curs = NULL;
+ return apr_dbm_open_db(pdb, pathname, mode, perm, pool);
+#elif APU_USE_GDBM
+ return apr_dbm_open_gdbm(pdb, pathname, mode, perm, pool);
#else
- file.bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
- DB_HASH, NULL);
- if (file.bdb == NULL)
- return APR_EGENERAL; /* ### need a better error */
- dberr = 0;
+ return APR_ENOTAVAIL;
#endif
- if (dberr != 0)
- return db2s(dberr);
- }
-
-#else
-#error apr_dbm_open has not been coded for this database type
-#endif /* switch on database types */
-
- /* we have an open database... return it */
- *pdb = apr_pcalloc(pool, sizeof(**pdb));
- (*pdb)->pool = pool;
- (*pdb)->file = file;
-
- /* ### register a cleanup to close the DBM? */
-
- return APR_SUCCESS;
}
-APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
+APU_DECLARE(void) apr_dbm_close(apr_dbm_t * dbm)
{
- APR_DBM_CLOSE(dbm->file);
+ dbm->type->close(dbm);
}
-APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
- apr_datum_t *pvalue)
+APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t * dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
{
- apr_status_t rv;
- cvt_datum_t ckey;
- result_datum_t rd;
-
- CONVERT_DATUM(ckey, &key);
- rv = APR_DBM_FETCH(dbm->file, ckey, rd);
- RETURN_DATUM(pvalue, rd);
-
- REGISTER_CLEANUP(dbm, pvalue);
-
- /* store the error info into DBM, and return a status code. Also, note
- that *pvalue should have been cleared on error. */
- return set_error(dbm, rv);
+ return dbm->type->fetch(dbm, key, pvalue);
}
-APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
+APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t * dbm, apr_datum_t key,
apr_datum_t value)
{
- apr_status_t rv;
- cvt_datum_t ckey;
- cvt_datum_t cvalue;
-
- CONVERT_DATUM(ckey, &key);
- CONVERT_DATUM(cvalue, &value);
- rv = APR_DBM_STORE(dbm->file, ckey, cvalue);
-
- /* store any error info into DBM, and return a status code. */
- return set_error(dbm, rv);
+ return dbm->type->store(dbm, key, value);
}
-APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
+APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t * dbm, apr_datum_t key)
{
- apr_status_t rv;
- cvt_datum_t ckey;
-
- CONVERT_DATUM(ckey, &key);
- rv = APR_DBM_DELETE(dbm->file, ckey);
-
- /* store any error info into DBM, and return a status code. */
- return set_error(dbm, rv);
+ return dbm->type->del(dbm, key);
}
-APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+APU_DECLARE(int) apr_dbm_exists(apr_dbm_t * dbm, apr_datum_t key)
{
- int exists;
- cvt_datum_t ckey;
-
- CONVERT_DATUM(ckey, &key);
-
-#if APU_USE_SDBM
- {
- apr_sdbm_datum_t value;
- if (apr_sdbm_fetch(dbm->file, &value, *ckey) != APR_SUCCESS) {
- exists = 0;
- }
- else
- exists = value.dptr != NULL;
- }
-#elif APU_USE_GDBM
- exists = gdbm_exists(dbm->file, *ckey) != 0;
-#elif APU_USE_DB
- {
- DBT data;
- int dberr = do_fetch(dbm->file.bdb, ckey, data);
-
- /* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
- that *any* error means it doesn't exist. */
- exists = dberr == 0;
- }
-#else
-#error apr_dbm_exists has not been coded for this database type
-#endif
- return exists;
+ return dbm->type->exists(dbm, key);
}
-APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t * dbm,
+ apr_datum_t * pkey)
{
- apr_status_t rv;
- result_datum_t rd;
-
- rv = APR_DBM_FIRSTKEY(dbm->file, rd);
- RETURN_DATUM(pkey, rd);
-
- REGISTER_CLEANUP(dbm, pkey);
-
- /* store any error info into DBM, and return a status code. */
- return set_error(dbm, rv);
+ return dbm->type->firstkey(dbm, pkey);
}
-APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t * dbm, apr_datum_t * pkey)
{
- apr_status_t rv;
- cvt_datum_t ckey;
- result_datum_t rd;
-
- CONVERT_DATUM(ckey, pkey);
- rv = APR_DBM_NEXTKEY(dbm->file, ckey, rd);
- RETURN_DATUM(pkey, rd);
-
- REGISTER_CLEANUP(dbm, pkey);
-
- /* store any error info into DBM, and return a status code. */
- return set_error(dbm, APR_SUCCESS);
+ return dbm->type->nextkey(dbm, pkey);
}
-APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t * dbm, apr_datum_t data)
{
-#ifdef NEEDS_CLEANUP
- (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
-#else
- APR_DBM_FREEDPTR(data.dptr);
-#endif
+ dbm->type->freedatum(dbm, data);
}
+
-APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t * dbm, int *errcode,
char *errbuf, apr_size_t errbufsize)
{
- if (errcode != NULL)
- *errcode = dbm->errcode;
-
- /* assert: errbufsize > 0 */
-
- if (dbm->errmsg == NULL)
- *errbuf = '\0';
- else
- (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
- return errbuf;
+ return dbm->type->geterror(dbm, errcode, errbuf, errbufsize);
}
-APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
+APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t * p,
const char *pathname,
const char **used1,
const char **used2)
{
#if APU_USE_SDBM
- char *work;
-
- *used1 = apr_pstrcat(p, pathname, APR_SDBM_DIRFEXT, NULL);
- *used2 = work = apr_pstrdup(p, *used1);
-
- /* we know the extension is 4 characters */
- memcpy(&work[strlen(work) - 4], APR_SDBM_PAGFEXT, 4);
-#elif APU_USE_GDBM || APU_USE_DB
- *used1 = apr_pstrdup(p, pathname);
- *used2 = NULL;
+ apr_dbm_get_usednames_sdbm(p, pathname, used1, used2);
+#elif APU_USE_DB
+ apr_dbm_get_usednames_db(p, pathname, used1, used2);
+#elif APU_USE_GDBM
+ apr_dbm_get_usednames_gdbm(p, pathname, used1, used2);
#else
-#error apr_dbm_get_usednames has not been coded for this database type
+ /* default op. no assumptions made */
+ fprintf(stderr, "This Database does not implement apr_dbm_get_usednames");
+ *used1 = NULL;
+ *used2 = NULL;
#endif
}