-lock support moved from dba_flatfile.c to dba.c

-flatfile, cdb, cdb_make use locking now
#locking is blocking per default use 'rt', 'wt', ct' or 'nt' for non blocking alias
#test access to a database file.
#locking uses flock() which will be emulated or warned if that is not eally
#possible in ext/standard/flock_compat.c
This commit is contained in:
Marcus Boerger 2002-11-08 01:03:53 +00:00
parent 28c2fb6681
commit 95018fc5c0
3 changed files with 89 additions and 103 deletions

View file

@ -26,6 +26,13 @@
#if HAVE_DBA
#include "ext/standard/flock_compat.h"
#include <stdio.h>
#include <fcntl.h>
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include "php_dba.h"
#include "ext/standard/info.h"
@ -79,7 +86,8 @@ ZEND_GET_MODULE(dba)
#endif
typedef struct dba_handler {
char *name;
char *name; /* handler name */
int lock; /* whether and how dba does locking */
int (*open)(dba_info *, char **error TSRMLS_DC);
void (*close)(dba_info * TSRMLS_DC);
char* (*fetch)(dba_info *, char *, int, int, int * TSRMLS_DC);
@ -144,14 +152,14 @@ typedef struct dba_handler {
/* a DBA handler must have specific routines */
#define DBA_NAMED_HND(name, x) \
#define DBA_NAMED_HND(name, x, lock) \
{\
#name, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \
#name, lock, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \
dba_exists_##x, dba_delete_##x, dba_firstkey_##x, dba_nextkey_##x, \
dba_optimize_##x, dba_sync_##x \
},
#define DBA_HND(x) DBA_NAMED_HND(x, x)
#define DBA_HND(x, lock) DBA_NAMED_HND(x, x, lock)
/* check whether the user has write access */
#define DBA_WRITE_CHECK \
@ -166,30 +174,30 @@ typedef struct dba_handler {
static dba_handler handler[] = {
#if DBA_GDBM
DBA_HND(gdbm)
DBA_HND(gdbm, DBA_LOCK_EXT)
#endif
#if DBA_DBM
DBA_HND(dbm)
DBA_HND(dbm, DBA_LOCK_EXT)
#endif
#if DBA_NDBM
DBA_HND(ndbm)
DBA_HND(ndbm, DBA_LOCK_EXT)
#endif
#if DBA_CDB
DBA_HND(cdb)
DBA_HND(cdb, DBA_LOCK_ALL)
#endif
#if DBA_CDB_BUILTIN
DBA_NAMED_HND(cdb_make, cdb)
DBA_NAMED_HND(cdb_make, cdb, DBA_LOCK_ALL)
#endif
#if DBA_DB2
DBA_HND(db2)
DBA_HND(db2, DBA_LOCK_EXT)
#endif
#if DBA_DB3
DBA_HND(db3)
DBA_HND(db3, DBA_LOCK_EXT)
#endif
#if DBA_FLATFILE
DBA_HND(flatfile)
DBA_HND(flatfile, DBA_LOCK_ALL)
#endif
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static int le_db;
@ -202,6 +210,13 @@ static void dba_close(dba_info *info TSRMLS_DC)
{
if (info->hnd) info->hnd->close(info TSRMLS_CC);
if (info->path) efree(info->path);
if (info->lock.fd) {
flock(info->lock.fd, LOCK_UN);
close(info->lock.fd);
info->lock.fd = 0;
}
if (info->lock.fp) php_stream_close(info->lock.fp);
if (info->lock.name) efree(info->lock.name);
efree(info);
}
/* }}} */
@ -297,6 +312,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
char *key = NULL, *error = NULL;
int keylen = 0;
int i;
int lock;
char mode[4], *pmode;
if(ac < 3) {
WRONG_PARAM_COUNT;
@ -350,20 +367,36 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
RETURN_FALSE;
}
switch (Z_STRVAL_PP(args[1])[0]) {
case 'c':
modenr = DBA_CREAT;
strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
pmode = &mode[0];
switch (*pmode++) {
case 'r':
modenr = DBA_READER;
lock = (hptr->lock & DBA_LOCK_READER) ? LOCK_SH : 0;
break;
case 'w':
modenr = DBA_WRITER;
break;
case 'r':
modenr = DBA_READER;
lock = (hptr->lock & DBA_LOCK_WRITER) ? LOCK_EX : 0;
break;
case 'n':
modenr = DBA_TRUNC;
lock = (hptr->lock & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
break;
case 'c':
modenr = DBA_CREAT;
lock = (hptr->lock & DBA_LOCK_CREAT) ? LOCK_EX : 0;
break;
default:
lock = 0;
modenr = 0;
}
if (*pmode=='t') {
pmode++;
lock |= LOCK_NB; /* test =: non blocking */
} else if (*pmode=='b') {
pmode++; /* default is blocking */
}
if (*pmode || !modenr) {
php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
FREENOW;
RETURN_FALSE;
@ -376,7 +409,21 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
info->argc = ac - 3;
info->argv = args + 3;
if (hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
if (lock) {
spprintf(&info->lock.name, 0, "%s.lck", info->path);
info->lock.fp = php_stream_open_wrapper(info->lock.name, "a+b", STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
if (info->lock.fp && php_stream_cast(info->lock.fp, PHP_STREAM_AS_FD, (void*)&info->lock.fd, 1) == FAILURE) {
dba_close(info TSRMLS_CC);
/* stream operation already wrote an error message */
FREENOW;
RETURN_FALSE;
}
if (!info->lock.fp || flock(info->lock.fd, lock)) {
error = "Unable to establish lock"; /* force failure exit */
}
}
if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
dba_close(info TSRMLS_CC);
php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", Z_STRVAL_PP(args[2]), error?": ":"", error?error:"");
FREENOW;

View file

@ -34,16 +34,6 @@
#include <sys/stat.h>
#include <fcntl.h>
#ifdef PHP_31
#include "os/nt/flock.h"
#else
#ifdef PHP_WIN32
#include "win32/flock.h"
#else
#include <sys/file.h>
#endif
#endif
#define FLATFILE_DATA flatfile *dba = info->dbf
#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
@ -51,14 +41,6 @@ DBA_OPEN_FUNC(flatfile)
{
char *fmode;
php_stream *fp;
int lock;
char *lockfn = NULL;
int lockfd = 0;
#if NFS_HACK
int last_try = 0;
struct stat sb;
int retries = 0;
#endif
info->dbf = emalloc(sizeof(flatfile));
memset(info->dbf, 0, sizeof(flatfile));
@ -66,78 +48,29 @@ DBA_OPEN_FUNC(flatfile)
switch(info->mode) {
case DBA_READER:
fmode = "r";
lock = 0;
break;
case DBA_WRITER:
fmode = "r+b";
lock = 1;
break;
case DBA_CREAT:
fmode = "a+b";
lock = 1;
break;
case DBA_TRUNC:
fmode = "w+b";
lock = 1;
break;
default:
efree(info->dbf);
return FAILURE; /* not possible */
}
if (lock) {
spprintf(&lockfn, 0, "%s.lck", info->path);
#if NFS_HACK
while((last_try = VCWD_STAT(lockfn, &sb))==0) {
retries++;
php_sleep(1);
if (retries>30)
break;
}
if (last_try!=0) {
lockfd = open(lockfn, O_RDWR|O_CREAT, 0644);
close(lockfd);
} else {
*error = "File appears to be locked";
efree(lockfn);
efree(info->dbf);
return FAILURE;
}
#else /* NFS_HACK */
lockfd = VCWD_OPEN_MODE(lockfn, O_RDWR|O_CREAT, 0644);
if (!lockfd || flock(lockfd, LOCK_EX)) {
if (lockfd)
close(lockfd);
efree(lockfn);
efree(info->dbf);
*error = "Unable to establish lock";
return FAILURE;
}
#endif /* else NFS_HACK */
}
fp = php_stream_open_wrapper(info->path, fmode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
if (!fp) {
*error = "Unable to open file";
#if NFS_HACK
VCWD_UNLINK(lockfn);
#else
if (lockfn) {
lockfd = VCWD_OPEN_MODE(lockfn, O_RDWR, 0644);
flock(lockfd, LOCK_UN);
close(lockfd);
}
#endif
efree(lockfn);
efree(info->dbf);
return FAILURE;
}
((flatfile*)info->dbf)->fp = fp;
((flatfile*)info->dbf)->lockfn = lockfn;
((flatfile*)info->dbf)->lockfd = lockfd;
return SUCCESS;
}
@ -146,17 +79,6 @@ DBA_CLOSE_FUNC(flatfile)
{
FLATFILE_DATA;
if (dba->lockfn) {
#if NFS_HACK
VCWD_UNLINK(dba->lockfn);
#else
/*dba->lockfd = VCWD_OPEN_MODE(dba->lockfn, O_RDWR, 0644);*/
flock(dba->lockfd, LOCK_UN);
close(dba->lockfd);
#endif
efree(dba->lockfn);
}
php_stream_close(dba->fp);
if (dba->nextkey.dptr)
efree(dba->nextkey.dptr);

View file

@ -24,12 +24,19 @@
#if HAVE_DBA
typedef enum {
/* do not allow 0 here */
DBA_READER = 1,
DBA_WRITER,
DBA_TRUNC,
DBA_CREAT
} dba_mode_t;
typedef struct dba_lock {
php_stream *fp;
int fd;
char *name;
} dba_lock;
typedef struct dba_info {
/* public */
void *dbf; /* ptr to private data or whatever */
@ -40,8 +47,18 @@ typedef struct dba_info {
zval ***argv;
/* private */
struct dba_handler *hnd;
dba_lock lock;
} dba_info;
#define DBA_LOCK_READER (1)
#define DBA_LOCK_WRITER (2)
#define DBA_LOCK_CREAT (4)
#define DBA_LOCK_TRUNC (8)
#define DBA_LOCK_EXT (0)
#define DBA_LOCK_ALL (DBA_LOCK_READER|DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
#define DBA_LOCK_WCT (DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
extern zend_module_entry dba_module_entry;
#define dba_module_ptr &dba_module_entry