diff options
author | Marcus Boerger <helly@php.net> | 2002-11-04 17:53:04 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2002-11-04 17:53:04 +0000 |
commit | 5be5c7f14f69ebb75129a90215fca6e047920ac0 (patch) | |
tree | 4b50e780029ecfd5fe1f09d9e35f4bbe221600bf | |
parent | a8d4bb9d287b58a67d2cb532a469ae40f1b07268 (diff) | |
download | php-git-5be5c7f14f69ebb75129a90215fca6e047920ac0.tar.gz |
incorporate cdb-0.75 as suggested by D. J. Bernstein
#dba now supports cdb_make
-rw-r--r-- | ext/dba/CREDITS | 2 | ||||
-rw-r--r-- | ext/dba/config.m4 | 17 | ||||
-rw-r--r-- | ext/dba/dba.c | 9 | ||||
-rw-r--r-- | ext/dba/dba_cdb.c | 169 | ||||
-rwxr-xr-x | ext/dba/install_cdb.sh | 6 | ||||
-rw-r--r-- | ext/dba/libcdb/cdb.c | 191 | ||||
-rw-r--r-- | ext/dba/libcdb/cdb.h | 55 | ||||
-rw-r--r-- | ext/dba/libcdb/cdb_make.c | 238 | ||||
-rw-r--r-- | ext/dba/libcdb/cdb_make.h | 63 | ||||
-rw-r--r-- | ext/dba/libcdb/uint32.c | 49 | ||||
-rw-r--r-- | ext/dba/libcdb/uint32.h | 39 | ||||
-rw-r--r-- | ext/dba/tests/dba_cdb.phpt | 2 | ||||
-rw-r--r-- | ext/dba/tests/dba_cdb_make.phpt | 35 | ||||
-rw-r--r-- | ext/dba/tests/dba_cdb_read.phpt | 6 |
14 files changed, 839 insertions, 42 deletions
diff --git a/ext/dba/CREDITS b/ext/dba/CREDITS index 2f06307693..370b3ea271 100644 --- a/ext/dba/CREDITS +++ b/ext/dba/CREDITS @@ -1,2 +1,2 @@ DBA -Sascha Schumann +Sascha Schumann, Marcus Boerger
\ No newline at end of file diff --git a/ext/dba/config.m4 b/ext/dba/config.m4 index de78258550..92b299f53c 100644 --- a/ext/dba/config.m4 +++ b/ext/dba/config.m4 @@ -38,9 +38,9 @@ AC_DEFUN(PHP_DBA_STD_ATTACH,[ dnl Print the result message AC_DEFUN(AC_DBA_STD_RESULT,[ - if test "$THIS_RESULT" = "yes"; then + if test "$THIS_RESULT" = "yes" -o "$THIS_RESULT" = "builtin"; then HAVE_DBA=1 - AC_MSG_RESULT(yes) + AC_MSG_RESULT($THIS_RESULT) else AC_MSG_RESULT(no) fi @@ -213,12 +213,18 @@ AC_DBA_STD_RESULT AC_ARG_WITH(cdb, [ --with-cdb[=DIR] Include CDB support],[ - if test "$withval" != "no"; then + if test "$withval" = "yes"; then + PHP_ADD_BUILD_DIR($ext_builddir/libcdb) + AC_DEFINE(DBA_CDB_MAKE, 1, [ ]) + AC_DEFINE(DBA_CDB, 1, [ ]) + cdb_sources="libcdb/cdb.c libcdb/cdb_make.c libcdb/uint32.c" + THIS_RESULT="builtin" + elif test "$withval" != "no"; then for i in /usr/local /usr $withval; do if test -f "$i/include/cdb.h" ; then THIS_PREFIX=$i fi - done + done for LIB in cdb c; do PHP_TEMP_LDFLAGS(-L$THIS_PREFIX/lib,[ @@ -238,9 +244,8 @@ AC_MSG_CHECKING(whether to enable DBA interface) if test "$HAVE_DBA" = "1"; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_DBA, 1, [ ]) - PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_db2.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db3.c, $ext_shared) + PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_db2.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db3.c $cdb_sources, $ext_shared) PHP_SUBST(DBA_SHARED_LIBADD) else AC_MSG_RESULT(no) fi - diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 74a320ad74..1e674b410c 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -143,13 +143,15 @@ typedef struct dba_handler { /* a DBA handler must have specific routines */ -#define DBA_HND(x) \ +#define DBA_NAMED_HND(name, x) \ {\ - #x, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \ + #name, 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) + /* check whether the user has write access */ #define DBA_WRITE_CHECK \ if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \ @@ -174,6 +176,9 @@ static dba_handler handler[] = { #if DBA_CDB DBA_HND(cdb) #endif +#if DBA_CDB_BUILTIN + DBA_NAMED_HND(cdb_make, cdb) +#endif #if DBA_DB2 DBA_HND(db2) #endif diff --git a/ext/dba/dba_cdb.c b/ext/dba/dba_cdb.c index 28b0a78596..ffa7c9bf63 100644 --- a/ext/dba/dba_cdb.c +++ b/ext/dba/dba_cdb.c @@ -32,48 +32,95 @@ #include <unistd.h> #include <fcntl.h> +#if DBA_CDB_BUILTIN +#include "libcdb/cdb.h" +#include "libcdb/cdb_make.h" +#include "libcdb/uint32.h" +#else #include <cdb.h> #include <uint32.h> +#endif #define CDB_INFO \ dba_cdb *cdb = (dba_cdb *) info->dbf typedef struct { struct cdb c; - int fd; +#if DBA_CDB_BUILTIN + struct cdb_make m; + php_stream *file; + int make; +#else + int file; +#endif uint32 eod; /* size of constant database */ uint32 pos; /* current position for traversing */ } dba_cdb; DBA_OPEN_FUNC(cdb) { - int gmode = 0; - int fd; +#if DBA_CDB_BUILTIN + php_stream* file = 0; + int make; +#else + int file = 0; +#endif dba_cdb *cdb; dba_info *pinfo = (dba_info *) info; switch (info->mode) { case DBA_READER: - gmode = O_RDONLY; break; - /* currently not supported: */ -#if 0 - case DBA_WRITER: - gmode = O_RDWR; break; +#if DBA_CDB_BUILTIN + make = 0; + file = php_stream_open_wrapper(info->path, "rb", STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL); + if (!file) { + return FAILURE; + } +#else + file = VCWD_OPEN(info->path, O_RDONLY); + if (file < 0) { + return FAILURE; + } +#endif + break; +#if DBA_CDB_BUILTIN + case DBA_TRUNC: + case DBA_CREAT: + make = 1; + file = php_stream_open_wrapper(info->path, "wb", STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL); + if (!file) { + return FAILURE; + } + break; + case DBA_WRITER: + return FAILURE; /* not supported */ #endif default: + /* currently not supported: */ return FAILURE; } - fd = VCWD_OPEN(info->path, gmode); - if (fd < 0) { + cdb = ecalloc(sizeof(dba_cdb), 1); + if (!cdb) { +#if DBA_CDB_BUILTIN + php_stream_close(cdb->file); +#else + close(cdb->file); +#endif return FAILURE; } - - cdb = emalloc(sizeof(dba_cdb)); - memset(cdb, 0, sizeof(dba_cdb)); - cdb_init(&cdb->c, fd); - cdb->fd = fd; +#if DBA_CDB_BUILTIN + if (make) { + cdb_make_start(&cdb->m, file TSRMLS_CC); + } else { + cdb_init(&cdb->c, file TSRMLS_CC); + } + cdb->make = make; +#else + cdb_init(&cdb->c, file); +#endif + cdb->file = file; pinfo->dbf = cdb; return SUCCESS; @@ -83,29 +130,51 @@ DBA_CLOSE_FUNC(cdb) { CDB_INFO; - /* cdb_free does not close associated fd */ + /* cdb_free does not close associated file */ +#if DBA_CDB_BUILTIN + if (cdb->make) { + cdb_make_finish(&cdb->m TSRMLS_CC); + } else { + cdb_free(&cdb->c TSRMLS_CC); + } + php_stream_close(cdb->file); +#else cdb_free(&cdb->c); - close(cdb->fd); + close(cdb->file); +#endif efree(cdb); } +#if DBA_CDB_BUILTIN +# define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos TSRMLS_CC) +# define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len TSRMLS_CC) +# define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len TSRMLS_CC) +#else +# define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos) +# define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len) +# define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len) +#endif + DBA_FETCH_FUNC(cdb) { CDB_INFO; unsigned int len; char *new_entry = NULL; -/* cdb_findstart(&cdb->c); */ - if (cdb_find(&cdb->c, key, keylen) == 1) { +#if DBA_CDB_BUILTIN + if (cdb->make) + return NULL; /* database was opened writeonly */ +#endif + if (php_cdb_find(&cdb->c, key, keylen) == 1) { while(skip--) { - if (cdb_findnext(&cdb->c, key, keylen) != 1) { + if (php_cdb_findnext(&cdb->c, key, keylen) != 1) { return NULL; } } len = cdb_datalen(&cdb->c); new_entry = emalloc(len+1); - if (cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) { + if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) { efree(new_entry); return NULL; } @@ -119,7 +188,16 @@ DBA_FETCH_FUNC(cdb) DBA_UPDATE_FUNC(cdb) { - /* if anyone figures out cdbmake.c, let me know */ +#if DBA_CDB_BUILTIN + CDB_INFO; + + if (!cdb->make) + return FAILURE; /* database was opened readonly */ + if (!mode) + return FAILURE; /* cdb_make dosn't know replace */ + if (cdb_make_add(&cdb->m, key, keylen, val, vallen TSRMLS_CC) != -1) + return SUCCESS; +#endif return FAILURE; } @@ -127,24 +205,49 @@ DBA_EXISTS_FUNC(cdb) { CDB_INFO; - if (cdb_find(&cdb->c, key, keylen) == 1) +#if DBA_CDB_BUILTIN + if (cdb->make) + return FAILURE; /* database was opened writeonly */ +#endif + if (php_cdb_find(&cdb->c, key, keylen) == 1) return SUCCESS; return FAILURE; } DBA_DELETE_FUNC(cdb) { - return FAILURE; + return FAILURE; /* cdb doesn't support delete */ } +/* {{{ cdb_file_read */ +#if DBA_CDB_BUILTIN +# define cdb_file_read(fildes, buf, size) php_stream_read(fildes, buf, size) +#else +# define cdb_file_read(fildes, buf, size) read(fildes, buf, size) +#endif +/* }}} */ #define CREAD(n) do { \ - if (read(cdb->fd, buf, n) < n) return NULL; \ + if (cdb_file_read(cdb->file, buf, n) < n) return NULL; \ } while (0) +/* {{{ cdb_file_lseek + php_stream_seek does not return actual position */ +#if DBA_CDB_BUILTIN +int cdb_file_lseek(php_stream *fp, off_t offset, int whence TSRMLS_DC) { + php_stream_seek(fp, offset, whence); + return php_stream_tell(fp); +} +#else +int cdb_file_lseek(int fd, off_t offset, int whence TSRMLS_DC) { + return lseek(fd, offset, whence); +} +#endif +/* }}} */ + #define CSEEK(n) do { \ if (n >= cdb->eod) return NULL; \ - if (lseek(cdb->fd, (off_t)n, SEEK_SET) != (off_t) n) return NULL; \ + if (cdb_file_lseek(cdb->file, (off_t)n, SEEK_SET TSRMLS_CC) != (off_t) n) return NULL; \ } while (0) @@ -155,6 +258,11 @@ DBA_FIRSTKEY_FUNC(cdb) char buf[8]; char *key; +#if DBA_CDB_BUILTIN + if (cdb->make) + return NULL; /* database was opened writeonly */ +#endif + cdb->eod = -1; CSEEK(0); CREAD(4); @@ -170,7 +278,7 @@ DBA_FIRSTKEY_FUNC(cdb) uint32_unpack(buf + 4, &dlen); key = emalloc(klen + 1); - if (read(cdb->fd, key, klen) < klen) { + if (cdb_file_read(cdb->file, key, klen) < klen) { efree(key); key = NULL; } else { @@ -191,13 +299,18 @@ DBA_NEXTKEY_FUNC(cdb) char buf[8]; char *key; +#if DBA_CDB_BUILTIN + if (cdb->make) + return NULL; /* database was opened writeonly */ +#endif + CSEEK(cdb->pos); CREAD(8); uint32_unpack(buf, &klen); uint32_unpack(buf + 4, &dlen); key = emalloc(klen + 1); - if (read(cdb->fd, key, klen) < klen) { + if (cdb_file_read(cdb->file, key, klen) < klen) { efree(key); key = NULL; } else { diff --git a/ext/dba/install_cdb.sh b/ext/dba/install_cdb.sh index 9bb83b8cc5..ce5f3cc856 100755 --- a/ext/dba/install_cdb.sh +++ b/ext/dba/install_cdb.sh @@ -1,10 +1,14 @@ #! /bin/sh +# You can use this script if you want to use an external cdb lib. If you +# compile php using --with-cdb the internal functions will be used and no +# external library is used so that this script is not necessary. +# # cdb-0.75 lacks support for installing header files and creating a # library which programs can link against. This shell script fills # the gap. # -# $Id: install_cdb.sh,v 1.1 2002-09-19 04:18:20 sas Exp $ +# $Id: install_cdb.sh,v 1.2 2002-11-04 17:53:04 helly Exp $ if test -r "cdb.a" && test -r "auto-str.c" && test -r "byte.a"; then : diff --git a/ext/dba/libcdb/cdb.c b/ext/dba/libcdb/cdb.c new file mode 100644 index 0000000000..e712521722 --- /dev/null +++ b/ext/dba/libcdb/cdb.c @@ -0,0 +1,191 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include "cdb.h" + +#ifndef EPROTO +# define EPROTO -15 /* cdb 0.75's default for PROTOless systems */ +#endif + +/* {{{ cdb_match */ +static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos TSRMLS_DC) +{ + char buf[32]; + int n; + + while (len > 0) { + n = sizeof(buf); + if (n > len) + n = len; + if (cdb_read(c, buf, n, pos TSRMLS_CC) == -1) + return -1; + if (memcmp(buf, key, n)) + return 0; + pos += n; + key += n; + len -= n; + } + return 1; +} +/* }}} */ + +/* {{{ cdb_hashadd */ +static uint32 cdb_hashadd(uint32 h, unsigned char c) +{ + h += (h << 5); + return h ^ c; +} +/* }}} */ + +/* {{{ cdb_hash */ +PHPAPI uint32 cdb_hash(char *buf, unsigned int len) +{ + uint32 h; + + h = CDB_HASHSTART; + while (len) { + h = cdb_hashadd(h, *buf++); + --len; + } + return h; +} +/* }}} */ + +/* {{{ cdb_free */ +PHPAPI void cdb_free(struct cdb *c TSRMLS_DC) +{ +} +/* }}} */ + +/* {{{ cdb_findstart */ +PHPAPI void cdb_findstart(struct cdb *c TSRMLS_DC) +{ + c->loop = 0; +} +/* }}} */ + +/* {{{ cdb_init */ +PHPAPI void cdb_init(struct cdb *c, php_stream *fp TSRMLS_DC) +{ + cdb_free(c TSRMLS_CC); + cdb_findstart(c TSRMLS_CC); + c->fp = fp; +} +/* }}} */ + +/* {{{ cdb_read */ +PHPAPI int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos TSRMLS_DC) +{ + if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) { + errno = EPROTO; + return -1; + } + while (len > 0) { + int r; + do { + r = php_stream_read(c->fp, buf, len); + } while ((r == -1) && (errno == EINTR)); + if (r == -1) + return -1; + if (r == 0) { + errno = EPROTO; + return -1; + } + buf += r; + len -= r; + } + return 0; +} +/* }}} */ + +/* {{{ cdb_findnext */ +PHPAPI int cdb_findnext(struct cdb *c, char *key, unsigned int len TSRMLS_DC) +{ + char buf[8]; + uint32 pos; + uint32 u; + + if (!c->loop) { + u = cdb_hash(key, len); + if (cdb_read(c, buf, 8, (u << 3) & 2047 TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf + 4,&c->hslots); + if (!c->hslots) + return 0; + uint32_unpack(buf, &c->hpos); + c->khash = u; + u >>= 8; + u %= c->hslots; + u <<= 3; + c->kpos = c->hpos + u; + } + + while (c->loop < c->hslots) { + if (cdb_read(c, buf, 8, c->kpos TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf + 4, &pos); + if (!pos) + return 0; + c->loop += 1; + c->kpos += 8; + if (c->kpos == c->hpos + (c->hslots << 3)) + c->kpos = c->hpos; + uint32_unpack(buf, &u); + if (u == c->khash) { + if (cdb_read(c, buf, 8, pos TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf, &u); + if (u == len) + switch(cdb_match(c, key, len, pos + 8 TSRMLS_CC)) { + case -1: + return -1; + case 1: + uint32_unpack(buf + 4, &c->dlen); + c->dpos = pos + 8 + len; + return 1; + } + } + } + + return 0; +} +/* }}} */ + +/* {{{ cdb_find */ +PHPAPI int cdb_find(struct cdb *c, char *key, unsigned int len TSRMLS_DC) +{ + cdb_findstart(c TSRMLS_CC); + return cdb_findnext(c, key, len TSRMLS_CC); +} +/* }}} */ diff --git a/ext/dba/libcdb/cdb.h b/ext/dba/libcdb/cdb.h new file mode 100644 index 0000000000..74dc6947d1 --- /dev/null +++ b/ext/dba/libcdb/cdb.h @@ -0,0 +1,55 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifndef CDB_H +#define CDB_H + +#include "uint32.h" + +#define CDB_HASHSTART 5381 + +struct cdb { + php_stream *fp; + uint32 loop; /* number of hash slots searched under this key */ + uint32 khash; /* initialized if loop is nonzero */ + uint32 kpos; /* initialized if loop is nonzero */ + uint32 hpos; /* initialized if loop is nonzero */ + uint32 hslots; /* initialized if loop is nonzero */ + uint32 dpos; /* initialized if cdb_findnext() returns 1 */ + uint32 dlen; /* initialized if cdb_findnext() returns 1 */ +}; + +PHPAPI uint32 cdb_hash(char *, unsigned int); + +PHPAPI void cdb_free(struct cdb * TSRMLS_DC); +PHPAPI void cdb_init(struct cdb *, php_stream *fp TSRMLS_DC); + +PHPAPI int cdb_read(struct cdb *, char *, unsigned int, uint32 TSRMLS_DC); + +PHPAPI void cdb_findstart(struct cdb * TSRMLS_DC); +PHPAPI int cdb_findnext(struct cdb *, char *, unsigned int TSRMLS_DC); +PHPAPI int cdb_find(struct cdb *, char *, unsigned int TSRMLS_DC); + +#define cdb_datapos(c) ((c)->dpos) +#define cdb_datalen(c) ((c)->dlen) + +#endif diff --git a/ext/dba/libcdb/cdb_make.c b/ext/dba/libcdb/cdb_make.c new file mode 100644 index 0000000000..3a7520b274 --- /dev/null +++ b/ext/dba/libcdb/cdb_make.c @@ -0,0 +1,238 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include "cdb.h" +#include "cdb_make.h" +#include "uint32.h" + +/* {{{ cdb_make_write */ +static int cdb_make_write(struct cdb_make *c, char *buf, uint32 sz TSRMLS_DC) { + return php_stream_write(c->fp, buf, sz) == sz ? 0 : -1; +} + +/* {{{ cdb_posplus */ +static int cdb_posplus(struct cdb_make *c, uint32 len) +{ + uint32 newpos = c->pos + len; + if (newpos < len) { + errno = ENOMEM; + return -1; + } + c->pos = newpos; + return 0; +} +/* }}} */ + +/* {{{ cdb_make_start */ +PHPAPI int cdb_make_start(struct cdb_make *c, php_stream * f TSRMLS_DC) +{ + c->head = 0; + c->split = 0; + c->hash = 0; + c->numentries = 0; + c->fp = f; + c->pos = sizeof(c->final); + if (php_stream_seek(f, c->pos, SEEK_SET) == -1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Fseek failed"); + return -1; + } + return php_stream_tell(c->fp); +} +/* }}} */ + +/* {{{ cdb_make_addend */ +PHPAPI int cdb_make_addend(struct cdb_make *c, unsigned int keylen, unsigned int datalen, uint32 h TSRMLS_DC) +{ + struct cdb_hplist *head; + + head = c->head; + if (!head || (head->num >= CDB_HPLIST)) { + head = (struct cdb_hplist *) + emalloc(sizeof(struct cdb_hplist)); + if (!head) + return -1; + head->num = 0; + head->next = c->head; + c->head = head; + } + head->hp[head->num].h = h; + head->hp[head->num].p = c->pos; + ++head->num; + ++c->numentries; + if (cdb_posplus(c,8) == -1) + return -1; + if (cdb_posplus(c, keylen) == -1) + return -1; + if (cdb_posplus(c, datalen) == -1) + return -1; + return 0; +} +/* }}} */ + +/* {{{ cdb_make_addbegin */ +PHPAPI int cdb_make_addbegin(struct cdb_make *c, unsigned int keylen, unsigned int datalen TSRMLS_DC) +{ + char buf[8]; + + if (keylen > 0xffffffff) { + errno = ENOMEM; + return -1; + } + if (datalen > 0xffffffff) { + errno = ENOMEM; + return -1; + } + + uint32_pack(buf, keylen); + uint32_pack(buf + 4, datalen); + if (cdb_make_write(c, buf, 8 TSRMLS_CC) != 0) + return -1; + return 0; +} + +/* {{{ cdb_make_add */ +PHPAPI int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen TSRMLS_DC) +{ + if (cdb_make_addbegin(c, keylen, datalen TSRMLS_CC) == -1) + return -1; + if (cdb_make_write(c, key, keylen TSRMLS_CC) != 0) + return -1; + if (cdb_make_write(c, data, datalen TSRMLS_CC) != 0) + return -1; + return cdb_make_addend(c, keylen, datalen, cdb_hash(key, keylen) TSRMLS_CC); +} +/* }}} */ + +/* {{{ cdb_make_finish */ +PHPAPI int cdb_make_finish(struct cdb_make *c TSRMLS_DC) +{ + char buf[8]; + int i; + uint32 len; + uint32 u; + uint32 memsize; + uint32 count; + uint32 where; + struct cdb_hplist *x; + struct cdb_hp *hp; + + for (i = 0;i < 256;++i) + c->count[i] = 0; + + for (x = c->head; x; x = x->next) { + i = x->num; + while (i--) + ++c->count[255 & x->hp[i].h]; + } + + memsize = 1; + for (i = 0;i < 256;++i) { + u = c->count[i] * 2; + if (u > memsize) + memsize = u; + } + + memsize += c->numentries; /* no overflow possible up to now */ + u = (uint32) 0 - (uint32) 1; + u /= sizeof(struct cdb_hp); + if (memsize > u) { + errno = ENOMEM; + return -1; + } + + c->split = (struct cdb_hp *) + emalloc(memsize * sizeof(struct cdb_hp)); + if (!c->split) + return -1; + + c->hash = c->split + c->numentries; + + u = 0; + for (i = 0;i < 256;++i) { + u += c->count[i]; /* bounded by numentries, so no overflow */ + c->start[i] = u; + } + + for (x = c->head; x; x = x->next) { + i = x->num; + while (i--) + c->split[--c->start[255 & x->hp[i].h]] = x->hp[i]; + } + + for (i = 0;i < 256;++i) { + count = c->count[i]; + + len = count + count; /* no overflow possible */ + uint32_pack(c->final + 8 * i,c->pos); + uint32_pack(c->final + 8 * i + 4,len); + + for (u = 0;u < len;++u) + c->hash[u].h = c->hash[u].p = 0; + + hp = c->split + c->start[i]; + for (u = 0;u < count;++u) { + where = (hp->h >> 8) % len; + while (c->hash[where].p) + if (++where == len) + where = 0; + c->hash[where] = *hp++; + } + + for (u = 0;u < len;++u) { + uint32_pack(buf, c->hash[u].h); + uint32_pack(buf + 4, c->hash[u].p); + if (cdb_make_write(c, buf, 8 TSRMLS_CC) != 0) + return -1; + if (cdb_posplus(c, 8) == -1) + return -1; + } + } + + if (c->split) + efree(c->split); + + for (x = c->head; x; c->head = x) { + x = x->next; + efree(c->head); + } + + if (php_stream_flush(c->fp) != 0) + return -1; + php_stream_rewind(c->fp); + if (php_stream_tell(c->fp) != 0) + return -1; + if (cdb_make_write(c, c->final, sizeof(c->final) TSRMLS_CC) != 0) + return -1; + return php_stream_flush(c->fp); +} +/* }}} */ diff --git a/ext/dba/libcdb/cdb_make.h b/ext/dba/libcdb/cdb_make.h new file mode 100644 index 0000000000..33e1ac6539 --- /dev/null +++ b/ext/dba/libcdb/cdb_make.h @@ -0,0 +1,63 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifndef CDB_MAKE_H +#define CDB_MAKE_H + +#include <stdio.h> +#include "uint32.h" + +#define CDB_HPLIST 1000 + +struct cdb_hp { + uint32 h; + uint32 p; +}; + +struct cdb_hplist { + struct cdb_hp hp[CDB_HPLIST]; + struct cdb_hplist *next; + int num; +} ; + +struct cdb_make { + /* char bspace[8192]; */ + char final[2048]; + uint32 count[256]; + uint32 start[256]; + struct cdb_hplist *head; + struct cdb_hp *split; /* includes space for hash */ + struct cdb_hp *hash; + uint32 numentries; + /* buffer b; */ + uint32 pos; + /* int fd; */ + php_stream * fp; +}; + +PHPAPI int cdb_make_start(struct cdb_make *, php_stream * TSRMLS_DC); +PHPAPI int cdb_make_addbegin(struct cdb_make *, unsigned int, unsigned int TSRMLS_DC); +PHPAPI int cdb_make_addend(struct cdb_make *, unsigned int, unsigned int, uint32 TSRMLS_DC); +PHPAPI int cdb_make_add(struct cdb_make *, char *, unsigned int, char *, unsigned int TSRMLS_DC); +PHPAPI int cdb_make_finish(struct cdb_make * TSRMLS_DC); + +#endif diff --git a/ext/dba/libcdb/uint32.c b/ext/dba/libcdb/uint32.c new file mode 100644 index 0000000000..261a002592 --- /dev/null +++ b/ext/dba/libcdb/uint32.c @@ -0,0 +1,49 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#include "uint32.h" + +/* {{{ uint32_pack */ +PHPAPI void uint32_pack(char *out, uint32 in) +{ + out[0] = in&0xff; in>>=8; + out[1] = in&0xff; in>>=8; + out[2] = in&0xff; in>>=8; + out[3] = in&0xff; +} +/* }}} */ + +/* {{{ uint32_unpack */ +PHPAPI void uint32_unpack(const char *in, uint32 *out) +{ + *out = (((uint32)(unsigned char)in[3])<<24) | + (((uint32)(unsigned char)in[2])<<16) | + (((uint32)(unsigned char)in[1])<<8) | + (((uint32)(unsigned char)in[0])); +} +/* }}} */ diff --git a/ext/dba/libcdb/uint32.h b/ext/dba/libcdb/uint32.h new file mode 100644 index 0000000000..e7ba9a5bec --- /dev/null +++ b/ext/dba/libcdb/uint32.h @@ -0,0 +1,39 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifndef UINT32_H +#define UINT32_H + +#if SIZEOF_INT == 4 +/* Most 32-bit and 64-bit systems have 32-bit ints */ +typedef unsigned int uint32; +#elif SIZEOF_LONG == 4 +/* 16-bit systems? */ +typedef unsigned long uint32; +#else +#error Need type which holds 32 bits +#endif + +PHPAPI void uint32_pack(char *out, uint32 in); +PHPAPI void uint32_unpack(const char *in, uint32 *out); + +#endif diff --git a/ext/dba/tests/dba_cdb.phpt b/ext/dba/tests/dba_cdb.phpt index c1828f550e..716773c2f6 100644 --- a/ext/dba/tests/dba_cdb.phpt +++ b/ext/dba/tests/dba_cdb.phpt @@ -4,7 +4,7 @@ DBA CDB handler test <?php require_once('skipif.inc'); if (!in_array('cdb', dba_handlers())) die('skip CDB handler not available'); - die('skip CDB currently supports only reading'); + die('skip CDB does not support replace or delete'); ?> --FILE-- <?php diff --git a/ext/dba/tests/dba_cdb_make.phpt b/ext/dba/tests/dba_cdb_make.phpt new file mode 100644 index 0000000000..57166d5674 --- /dev/null +++ b/ext/dba/tests/dba_cdb_make.phpt @@ -0,0 +1,35 @@ +--TEST-- +DBA CDB_MAKE handler test +--SKIPIF-- +<?php + require_once('skipif.inc'); + if (!in_array('cdb_make', dba_handlers())) die('skip CDB_MAKE handler not available'); +?> +--FILE-- +<?php + require_once('test.inc'); + $handler = 'cdb_make'; + echo "database handler: $handler\n"; + // print md5 checksum of test.cdb which is generated by cdb_make program + var_dump(md5(implode('',file(dirname(__FILE__).'/test.cdb')))); + if (($db_make=dba_open($db_file, "n", $handler))!==FALSE) { + dba_insert("1", "1", $db_make); + dba_insert("2", "2", $db_make); + dba_insert("1", "3", $db_make); + dba_insert("2", "1", $db_make); + dba_insert("3", "3", $db_make); + dba_insert("1", "2", $db_make); + dba_insert("4", "4", $db_make); +// dba_replace cdb_make doesn't know replace + dba_close($db_make); + // write md5 checksum of generated database file + var_dump(md5(implode('',file($db_file)))); + // no need to test created database: this is done by dba_cdb_read.phpt + } else { + echo "Error creating database\n"; + } +?> +--EXPECT-- +database handler: cdb_make +string(32) "723d19f39c1b15b3b455dd64323148d1" +string(32) "723d19f39c1b15b3b455dd64323148d1"
\ No newline at end of file diff --git a/ext/dba/tests/dba_cdb_read.phpt b/ext/dba/tests/dba_cdb_read.phpt index 045de9574a..573a58cee3 100644 --- a/ext/dba/tests/dba_cdb_read.phpt +++ b/ext/dba/tests/dba_cdb_read.phpt @@ -33,8 +33,8 @@ DBA CDB handler test (read only) echo "\n#"; echo dba_fetch(1, $db_file); echo dba_fetch(1, $db_file); - echo dba_fetch(1, $db_file); - echo dba_fetch(1, $db_file); + echo dba_fetch(2, $db_file); + echo dba_fetch(2, $db_file); echo "\n?".$keys; // with skip = 0 dba_fetch must fetch the first result echo "\n#"; @@ -59,7 +59,7 @@ DBA CDB handler test (read only) database handler: cdb 7YYYYNNN =1234 -#1111 +#1122 ?1212314 #1212314 =1231324
\ No newline at end of file |