mod_socache_dbm.c revision 027f7b141f164258b254c38319d06452b25d7660
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "httpd.h"
#include "http_log.h"
#include "http_request.h"
#include "http_protocol.h"
#include "http_config.h"
#include "mpm_common.h"
#include "apr.h"
#include "apr_strings.h"
#include "apr_time.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apr_dbm.h"
#include <unistd.h>
#endif
#include "ap_socache.h"
#include "unixd.h"
#endif
/* Use of the context structure must be thread-safe after the initial
struct ap_socache_instance_t {
const char *data_file;
/* Pool must only be used with the mutex held. */
};
/**
* Support for DBM library
*/
/* ### this should use apr_dbm_usednames. */
#if !defined(DBM_FILE_SUFFIX_DIR) && !defined(DBM_FILE_SUFFIX_PAG)
#if defined(DBM_SUFFIX)
#define DBM_FILE_SUFFIX_DIR DBM_SUFFIX
#define DBM_FILE_SUFFIX_PAG DBM_SUFFIX
#define DBM_FILE_SUFFIX_DIR ".db"
#define DBM_FILE_SUFFIX_PAG ".db"
#else
#define DBM_FILE_SUFFIX_DIR ".dir"
#define DBM_FILE_SUFFIX_PAG ".pag"
#endif
#endif
server_rec *s, const unsigned char *id,
unsigned int idlen, apr_pool_t *p);
const char *arg,
{
}
}
return NULL;
}
const char *namespace,
const struct ap_socache_hints *hints,
server_rec *s, apr_pool_t *p)
{
/* for the DBM we need the data file */
NULL);
"could not use default path '%s' for DBM socache",
path);
return APR_EINVAL;
}
}
/* open it once to create it and to make sure it _can_ be created */
"Cannot create socache DBM file `%s'",
return rv;
}
/*
* We have to make sure the Apache child processes have access to
* the DBM file. But because there are brain-dead platforms where we
* cannot exactly determine the suffixes we try all possibilities.
*/
if (geteuid() == 0 /* is superuser */) {
}
}
}
#endif
socache_dbm_expire(ctx, s);
return APR_SUCCESS;
}
{
/* the correct way */
/* the additional ways to be sure */
return;
}
server_rec *s, const unsigned char *id,
unsigned char *ucaData,
{
/* be careful: do not try to store too much bytes in a DBM file! */
#ifdef PAIRMAX
"data size too large for DBM socache: %d >= %d",
return APR_ENOSPC;
}
#else
"data size too large for DBM socache: %d >= %d",
return APR_ENOSPC;
}
#endif
/* create DBM key */
/* create DBM value */
"malloc error creating DBM value");
return APR_ENOMEM;
}
/* and store it to the DBM file */
"Cannot open socache DBM file `%s' for writing "
"(store)",
return rv;
}
"Cannot store socache object to DBM file `%s'",
return rv;
}
/* free temporary buffers */
/* allow the regular expiring to occur */
socache_dbm_expire(ctx, s);
return APR_SUCCESS;
}
apr_pool_t *p)
{
unsigned int nData;
/* allow the regular expiring to occur */
socache_dbm_expire(ctx, s);
/* create DBM key and values */
/* and fetch it from the DBM file
* XXX: Should we open the dbm against r->pool so the cleanup will
* do the apr_dbm_close? This would make the code a bit cleaner.
*/
"Cannot open socache DBM file `%s' for reading "
"(fetch)",
return rc;
}
if (rc != APR_SUCCESS) {
return APR_NOTFOUND;
}
return APR_EGENERAL;
}
/* parse resulting data */
return APR_ENOSPC;
}
/* make sure the stuff is still not expired */
now = apr_time_now();
return APR_NOTFOUND;
}
return APR_SUCCESS;
}
server_rec *s, const unsigned char *id,
unsigned int idlen, apr_pool_t *p)
{
/* create DBM key and values */
/* and delete it from the DBM file */
"Cannot open socache DBM file `%s' for writing "
"(delete)",
return rv;
}
return APR_SUCCESS;
}
{
int elts = 0;
int deleted = 0;
int expired;
int keyidx;
int i;
/*
* make sure the expiration for still not-accessed
* socache entries is done only from time to time
*/
now = apr_time_now();
return;
}
/*
* Here we have to be very carefully: Not all DBM libraries are
* smart enough to allow one to iterate over the elements and at the
* same time delete expired ones. Some of them get totally crazy
* while others have no problems. So we have to do it the slower but
* more safe way: we first iterate over all elements and remember
* those which have to be expired. Then in a second pass we delete
* all those expired elements. Additionally we reopen the DBM file
* to be really safe in state.
*/
#define KEYMAX 1024
for (;;) {
/* allocate the key array in a memory sub pool */
break;
}
/* pass 1: scan DBM database */
keyidx = 0;
"Cannot open socache DBM file `%s' for "
"scanning",
break;
}
elts++;
else {
}
if (expired) {
keyidx++;
break;
}
}
}
/* pass 2: delete expired elements */
"Cannot re-open socache DBM file `%s' for "
"expiring",
break;
}
for (i = 0; i < keyidx; i++) {
deleted++;
}
break;
}
"DBM socache expiry: "
"old: %d, new: %d, removed: %d",
}
int flags)
{
int elts;
long size;
int avg;
elts = 0;
size = 0;
"Cannot open socache DBM file `%s' for status "
"retrival",
return;
}
/*
* XXX - Check the return value of apr_dbm_firstkey, apr_dbm_fetch - TBD
*/
continue;
elts += 1;
}
else
avg = 0;
ap_rprintf(r, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>");
return;
}
server_rec *s, void *userctx,
{
int expired;
/*
* make sure the expired records are omitted
*/
now = apr_time_now();
"Cannot open socache DBM file `%s' for "
return rv;
}
else {
}
if (!expired) {
if (rv != APR_SUCCESS)
return rv;
}
}
return rv;
}
return APR_SUCCESS;
}
static const ap_socache_provider_t socache_dbm = {
"dbm",
};
static void register_hooks(apr_pool_t *p)
{
&socache_dbm);
}
};