-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 #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 "php_dba.h"
#include "ext/standard/info.h" #include "ext/standard/info.h"
@ -79,7 +86,8 @@ ZEND_GET_MODULE(dba)
#endif #endif
typedef struct dba_handler { 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); int (*open)(dba_info *, char **error TSRMLS_DC);
void (*close)(dba_info * TSRMLS_DC); void (*close)(dba_info * TSRMLS_DC);
char* (*fetch)(dba_info *, char *, int, int, int * 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 */ /* 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_exists_##x, dba_delete_##x, dba_firstkey_##x, dba_nextkey_##x, \
dba_optimize_##x, dba_sync_##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 */ /* check whether the user has write access */
#define DBA_WRITE_CHECK \ #define DBA_WRITE_CHECK \
@ -166,30 +174,30 @@ typedef struct dba_handler {
static dba_handler handler[] = { static dba_handler handler[] = {
#if DBA_GDBM #if DBA_GDBM
DBA_HND(gdbm) DBA_HND(gdbm, DBA_LOCK_EXT)
#endif #endif
#if DBA_DBM #if DBA_DBM
DBA_HND(dbm) DBA_HND(dbm, DBA_LOCK_EXT)
#endif #endif
#if DBA_NDBM #if DBA_NDBM
DBA_HND(ndbm) DBA_HND(ndbm, DBA_LOCK_EXT)
#endif #endif
#if DBA_CDB #if DBA_CDB
DBA_HND(cdb) DBA_HND(cdb, DBA_LOCK_ALL)
#endif #endif
#if DBA_CDB_BUILTIN #if DBA_CDB_BUILTIN
DBA_NAMED_HND(cdb_make, cdb) DBA_NAMED_HND(cdb_make, cdb, DBA_LOCK_ALL)
#endif #endif
#if DBA_DB2 #if DBA_DB2
DBA_HND(db2) DBA_HND(db2, DBA_LOCK_EXT)
#endif #endif
#if DBA_DB3 #if DBA_DB3
DBA_HND(db3) DBA_HND(db3, DBA_LOCK_EXT)
#endif #endif
#if DBA_FLATFILE #if DBA_FLATFILE
DBA_HND(flatfile) DBA_HND(flatfile, DBA_LOCK_ALL)
#endif #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; static int le_db;
@ -200,8 +208,15 @@ static int le_pdb;
*/ */
static void dba_close(dba_info *info TSRMLS_DC) static void dba_close(dba_info *info TSRMLS_DC)
{ {
if(info->hnd) info->hnd->close(info TSRMLS_CC); if (info->hnd) info->hnd->close(info TSRMLS_CC);
if(info->path) efree(info->path); 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); efree(info);
} }
/* }}} */ /* }}} */
@ -297,6 +312,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
char *key = NULL, *error = NULL; char *key = NULL, *error = NULL;
int keylen = 0; int keylen = 0;
int i; int i;
int lock;
char mode[4], *pmode;
if(ac < 3) { if(ac < 3) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
@ -350,23 +367,39 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
RETURN_FALSE; RETURN_FALSE;
} }
switch (Z_STRVAL_PP(args[1])[0]) { strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
case 'c': pmode = &mode[0];
modenr = DBA_CREAT; switch (*pmode++) {
case 'r':
modenr = DBA_READER;
lock = (hptr->lock & DBA_LOCK_READER) ? LOCK_SH : 0;
break; break;
case 'w': case 'w':
modenr = DBA_WRITER; modenr = DBA_WRITER;
break; lock = (hptr->lock & DBA_LOCK_WRITER) ? LOCK_EX : 0;
case 'r':
modenr = DBA_READER;
break; break;
case 'n': case 'n':
modenr = DBA_TRUNC; 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; break;
default: default:
php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode"); lock = 0;
FREENOW; modenr = 0;
RETURN_FALSE; }
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;
} }
info = emalloc(sizeof(dba_info)); info = emalloc(sizeof(dba_info));
@ -376,7 +409,21 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
info->argc = ac - 3; info->argc = ac - 3;
info->argv = args + 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); 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:""); 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; FREENOW;

View file

@ -34,16 +34,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.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_DATA flatfile *dba = info->dbf
#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen #define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
@ -51,14 +41,6 @@ DBA_OPEN_FUNC(flatfile)
{ {
char *fmode; char *fmode;
php_stream *fp; 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)); info->dbf = emalloc(sizeof(flatfile));
memset(info->dbf, 0, sizeof(flatfile)); memset(info->dbf, 0, sizeof(flatfile));
@ -66,78 +48,29 @@ DBA_OPEN_FUNC(flatfile)
switch(info->mode) { switch(info->mode) {
case DBA_READER: case DBA_READER:
fmode = "r"; fmode = "r";
lock = 0;
break; break;
case DBA_WRITER: case DBA_WRITER:
fmode = "r+b"; fmode = "r+b";
lock = 1;
break; break;
case DBA_CREAT: case DBA_CREAT:
fmode = "a+b"; fmode = "a+b";
lock = 1;
break; break;
case DBA_TRUNC: case DBA_TRUNC:
fmode = "w+b"; fmode = "w+b";
lock = 1;
break; break;
default: default:
efree(info->dbf); efree(info->dbf);
return FAILURE; /* not possible */ 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); fp = php_stream_open_wrapper(info->path, fmode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
if (!fp) { if (!fp) {
*error = "Unable to open file"; *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); efree(info->dbf);
return FAILURE; return FAILURE;
} }
((flatfile*)info->dbf)->fp = fp; ((flatfile*)info->dbf)->fp = fp;
((flatfile*)info->dbf)->lockfn = lockfn;
((flatfile*)info->dbf)->lockfd = lockfd;
return SUCCESS; return SUCCESS;
} }
@ -146,17 +79,6 @@ DBA_CLOSE_FUNC(flatfile)
{ {
FLATFILE_DATA; 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); php_stream_close(dba->fp);
if (dba->nextkey.dptr) if (dba->nextkey.dptr)
efree(dba->nextkey.dptr); efree(dba->nextkey.dptr);

View file

@ -24,12 +24,19 @@
#if HAVE_DBA #if HAVE_DBA
typedef enum { typedef enum {
/* do not allow 0 here */
DBA_READER = 1, DBA_READER = 1,
DBA_WRITER, DBA_WRITER,
DBA_TRUNC, DBA_TRUNC,
DBA_CREAT DBA_CREAT
} dba_mode_t; } dba_mode_t;
typedef struct dba_lock {
php_stream *fp;
int fd;
char *name;
} dba_lock;
typedef struct dba_info { typedef struct dba_info {
/* public */ /* public */
void *dbf; /* ptr to private data or whatever */ void *dbf; /* ptr to private data or whatever */
@ -40,8 +47,18 @@ typedef struct dba_info {
zval ***argv; zval ***argv;
/* private */ /* private */
struct dba_handler *hnd; struct dba_handler *hnd;
dba_lock lock;
} dba_info; } 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; extern zend_module_entry dba_module_entry;
#define dba_module_ptr &dba_module_entry #define dba_module_ptr &dba_module_entry