mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add support to pass driver flags to DBA handlers
Currently only LMDB with DBA_LMDB_USE_SUB_DIR/DBA_LMDB_NO_SUB_DIR are supported
This commit is contained in:
parent
79d831ff9f
commit
3c372901bd
10 changed files with 163 additions and 10 deletions
1
NEWS
1
NEWS
|
@ -15,6 +15,7 @@ PHP NEWS
|
||||||
|
|
||||||
- DBA:
|
- DBA:
|
||||||
. Fixed LMDB driver memory leak on DB creation failure (Girgias)
|
. Fixed LMDB driver memory leak on DB creation failure (Girgias)
|
||||||
|
. Fixed GH-8856 (dba: lmdb: allow to override the MDB_NOSUBDIR flag). (Girgias)
|
||||||
|
|
||||||
- Random:
|
- Random:
|
||||||
. Fixed bug GH-9067 (random extension is not thread safe). (cmb)
|
. Fixed bug GH-9067 (random extension is not thread safe). (cmb)
|
||||||
|
|
|
@ -88,6 +88,11 @@ PHP 8.2 UPGRADE NOTES
|
||||||
. Exposed multiple new constants from libcurl 7.62 to 7.80.
|
. Exposed multiple new constants from libcurl 7.62 to 7.80.
|
||||||
. Added new function curl_upkeep() to perform any connection upkeep checks.
|
. Added new function curl_upkeep() to perform any connection upkeep checks.
|
||||||
|
|
||||||
|
- DBA:
|
||||||
|
. The LMDB Driver now accepts the DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR
|
||||||
|
flags to determine if it should create a sub directory or not when creating
|
||||||
|
a database file.
|
||||||
|
|
||||||
- OCI8:
|
- OCI8:
|
||||||
. Added an oci8.prefetch_lob_size directive and oci_set_prefetch_lob()
|
. Added an oci8.prefetch_lob_size directive and oci_set_prefetch_lob()
|
||||||
function to tune LOB query performance by reducing the number of
|
function to tune LOB query performance by reducing the number of
|
||||||
|
@ -183,7 +188,7 @@ PHP 8.2 UPGRADE NOTES
|
||||||
|
|
||||||
- DBA
|
- DBA
|
||||||
. dba_open() and dba_popen() now have the following enforced function signature
|
. dba_open() and dba_popen() now have the following enforced function signature
|
||||||
dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0)
|
dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null)
|
||||||
. dba_fetch()'s optional skip argument is now at the end in line with
|
. dba_fetch()'s optional skip argument is now at the end in line with
|
||||||
PHP userland semantics its signature now is:
|
PHP userland semantics its signature now is:
|
||||||
dba_fetch(string|array $key, $dba, int $skip = 0): string|false
|
dba_fetch(string|array $key, $dba, int $skip = 0): string|false
|
||||||
|
|
|
@ -359,6 +359,7 @@ PHP_MINIT_FUNCTION(dba)
|
||||||
REGISTER_INI_ENTRIES();
|
REGISTER_INI_ENTRIES();
|
||||||
le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
|
le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
|
||||||
le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
|
le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
|
||||||
|
register_dba_symbols(module_number);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -478,10 +479,12 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
||||||
zend_string *handler_str = NULL;
|
zend_string *handler_str = NULL;
|
||||||
zend_long permission = 0644;
|
zend_long permission = 0644;
|
||||||
zend_long map_size = 0;
|
zend_long map_size = 0;
|
||||||
|
zend_long driver_flags = DBA_DEFAULT_DRIVER_FLAGS;
|
||||||
|
bool is_flags_null = true;
|
||||||
zend_string *persistent_resource_key = NULL;
|
zend_string *persistent_resource_key = NULL;
|
||||||
|
|
||||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!ll", &path, &mode, &handler_str,
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!lll!", &path, &mode, &handler_str,
|
||||||
&permission, &map_size)) {
|
&permission, &map_size, &driver_flags, &is_flags_null)) {
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +506,11 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_flags_null && driver_flags < 0) {
|
||||||
|
zend_argument_value_error(6, "must be greater or equal than 0");
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
if (persistent) {
|
if (persistent) {
|
||||||
zend_resource *le;
|
zend_resource *le;
|
||||||
|
|
||||||
|
@ -720,6 +728,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
||||||
info->mode = modenr;
|
info->mode = modenr;
|
||||||
info->file_permission = permission;
|
info->file_permission = permission;
|
||||||
info->map_size = map_size;
|
info->map_size = map_size;
|
||||||
|
info->driver_flags = driver_flags;
|
||||||
info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
|
info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
|
||||||
info->lock.mode = lock_mode;
|
info->lock.mode = lock_mode;
|
||||||
|
|
||||||
|
@ -835,9 +844,15 @@ restart:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error || hptr->open(info, &error) != SUCCESS) {
|
if (error || hptr->open(info, &error) == FAILURE) {
|
||||||
dba_close(info);
|
dba_close(info);
|
||||||
php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
|
if (EXPECTED(!EG(exception))) {
|
||||||
|
if (error) {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s: %s", hptr->name, error);
|
||||||
|
} else {
|
||||||
|
php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s", hptr->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
FREE_PERSISTENT_RESOURCE_KEY();
|
FREE_PERSISTENT_RESOURCE_KEY();
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,21 @@
|
||||||
|
|
||||||
/** @generate-class-entries */
|
/** @generate-class-entries */
|
||||||
|
|
||||||
/** @return resource|false */
|
#ifdef DBA_LMDB
|
||||||
function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) {}
|
/** @var int */
|
||||||
|
const DBA_LMDB_USE_SUB_DIR = 0;
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
* @cvalue MDB_NOSUBDIR
|
||||||
|
*/
|
||||||
|
const DBA_LMDB_NO_SUB_DIR = UNKNOWN;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @return resource|false */
|
/** @return resource|false */
|
||||||
function dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) {}
|
function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {}
|
||||||
|
|
||||||
|
/** @return resource|false */
|
||||||
|
function dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {}
|
||||||
|
|
||||||
/** @param resource $dba */
|
/** @param resource $dba */
|
||||||
function dba_close($dba): void {}
|
function dba_close($dba): void {}
|
||||||
|
|
13
ext/dba/dba_arginfo.h
generated
13
ext/dba/dba_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: 1957dd08c4efcfa765bd15c8d9ae9e69edec5db5 */
|
* Stub hash: 1a02eaf9da45edb40720620e3beef43fd19dd520 */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
|
||||||
ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0)
|
||||||
|
@ -7,6 +7,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
|
||||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, handler, IS_STRING, 1, "null")
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, handler, IS_STRING, 1, "null")
|
||||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permission, IS_LONG, 0, "0644")
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permission, IS_LONG, 0, "0644")
|
||||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, map_size, IS_LONG, 0, "0")
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, map_size, IS_LONG, 0, "0")
|
||||||
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 1, "null")
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
#define arginfo_dba_open arginfo_dba_popen
|
#define arginfo_dba_open arginfo_dba_popen
|
||||||
|
@ -95,3 +96,13 @@ static const zend_function_entry ext_functions[] = {
|
||||||
ZEND_FE(dba_list, arginfo_dba_list)
|
ZEND_FE(dba_list, arginfo_dba_list)
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void register_dba_symbols(int module_number)
|
||||||
|
{
|
||||||
|
#if defined(DBA_LMDB)
|
||||||
|
REGISTER_LONG_CONSTANT("DBA_LMDB_USE_SUB_DIR", 0, CONST_CS | CONST_PERSISTENT);
|
||||||
|
#endif
|
||||||
|
#if defined(DBA_LMDB)
|
||||||
|
REGISTER_LONG_CONSTANT("DBA_LMDB_NO_SUB_DIR", MDB_NOSUBDIR, CONST_CS | CONST_PERSISTENT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -40,12 +40,28 @@ DBA_OPEN_FUNC(lmdb)
|
||||||
{
|
{
|
||||||
MDB_env *env;
|
MDB_env *env;
|
||||||
MDB_txn *txn;
|
MDB_txn *txn;
|
||||||
int rc, flags = MDB_NOSUBDIR;
|
int rc;
|
||||||
int mode = info->file_permission;
|
int mode = info->file_permission;
|
||||||
zend_long map_size = info->map_size;
|
zend_long map_size = info->map_size;
|
||||||
|
|
||||||
ZEND_ASSERT(map_size >= 0);
|
ZEND_ASSERT(map_size >= 0);
|
||||||
|
|
||||||
|
/* By default use the MDB_NOSUBDIR flag */
|
||||||
|
int flags = MDB_NOSUBDIR;
|
||||||
|
/* Use flags passed by the user for driver flags */
|
||||||
|
if (info->driver_flags != DBA_DEFAULT_DRIVER_FLAGS) {
|
||||||
|
ZEND_ASSERT(info->driver_flags >= 0);
|
||||||
|
switch (info->driver_flags) {
|
||||||
|
case 0:
|
||||||
|
case MDB_NOSUBDIR:
|
||||||
|
flags = info->driver_flags;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zend_argument_value_error(6, "must be either DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR for LMDB driver");
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add readonly flag if DB is opened in read only mode */
|
/* Add readonly flag if DB is opened in read only mode */
|
||||||
if (info->mode == DBA_READER) {
|
if (info->mode == DBA_READER) {
|
||||||
flags |= MDB_RDONLY;
|
flags |= MDB_RDONLY;
|
||||||
|
|
|
@ -44,12 +44,16 @@ typedef struct dba_info {
|
||||||
int fd;
|
int fd;
|
||||||
int file_permission;
|
int file_permission;
|
||||||
zend_long map_size;
|
zend_long map_size;
|
||||||
|
/* -1 for default driver flags */
|
||||||
|
zend_long driver_flags;
|
||||||
/* private */
|
/* private */
|
||||||
int flags; /* whether and how dba did locking and other flags*/
|
int flags; /* whether and how dba did locking and other flags*/
|
||||||
struct dba_handler *hnd;
|
struct dba_handler *hnd;
|
||||||
dba_lock lock;
|
dba_lock lock;
|
||||||
} dba_info;
|
} dba_info;
|
||||||
|
|
||||||
|
#define DBA_DEFAULT_DRIVER_FLAGS -1
|
||||||
|
|
||||||
#define DBA_LOCK_READER (0x0001)
|
#define DBA_LOCK_READER (0x0001)
|
||||||
#define DBA_LOCK_WRITER (0x0002)
|
#define DBA_LOCK_WRITER (0x0002)
|
||||||
#define DBA_LOCK_CREAT (0x0004)
|
#define DBA_LOCK_CREAT (0x0004)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#ifdef DBA_LMDB
|
#ifdef DBA_LMDB
|
||||||
|
|
||||||
#include "php_dba.h"
|
#include "php_dba.h"
|
||||||
|
#include <lmdb.h>
|
||||||
|
|
||||||
DBA_FUNCS(lmdb);
|
DBA_FUNCS(lmdb);
|
||||||
|
|
||||||
|
|
14
ext/dba/tests/dba_flags_arg.phpt
Normal file
14
ext/dba/tests/dba_flags_arg.phpt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
DBA new flags ValueError test
|
||||||
|
--EXTENSIONS--
|
||||||
|
dba
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
try {
|
||||||
|
dba_open('irrelevant', 'c', 'handler', flags: -1);
|
||||||
|
} catch (\ValueError $e) {
|
||||||
|
echo $e->getMessage(), \PHP_EOL;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
dba_open(): Argument #6 ($flags) must be greater or equal than 0
|
76
ext/dba/tests/dba_lmdb_flags.phpt
Normal file
76
ext/dba/tests/dba_lmdb_flags.phpt
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
--TEST--
|
||||||
|
DBA LMDB handler flags test
|
||||||
|
--EXTENSIONS--
|
||||||
|
dba
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
$handler = 'lmdb';
|
||||||
|
require_once __DIR__ .'/skipif.inc';
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$handler = 'lmdb';
|
||||||
|
|
||||||
|
// Pass bogus flag
|
||||||
|
try {
|
||||||
|
$db_file = dba_open('irrelevant', 'c', $handler, flags: 45);
|
||||||
|
} catch (\ValueError $e) {
|
||||||
|
echo $e->getMessage(), \PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use current test folder
|
||||||
|
$db_filename = __DIR__;
|
||||||
|
$db_file = dba_open($db_filename, 'c', $handler, flags: DBA_LMDB_USE_SUB_DIR);
|
||||||
|
assert($db_file !== false);
|
||||||
|
|
||||||
|
// Check insertion of data
|
||||||
|
dba_insert("key1", "Content String 1", $db_file);
|
||||||
|
dba_insert("key2", "Content String 2", $db_file);
|
||||||
|
dba_insert("key3", "Third Content String", $db_file);
|
||||||
|
dba_insert("key4", "Another Content String", $db_file);
|
||||||
|
dba_insert("key5", "The last content string", $db_file);
|
||||||
|
|
||||||
|
// Remove some data
|
||||||
|
dba_delete("key3", $db_file);
|
||||||
|
dba_delete("key1", $db_file);
|
||||||
|
|
||||||
|
// Fetch data
|
||||||
|
$key = dba_firstkey($db_file);
|
||||||
|
$total_keys = 0;
|
||||||
|
while ($key) {
|
||||||
|
echo $key, ': ', dba_fetch($key, $db_file), \PHP_EOL;
|
||||||
|
$key = dba_nextkey($db_file);
|
||||||
|
$total_keys++;
|
||||||
|
}
|
||||||
|
echo 'Total keys: ', $total_keys, \PHP_EOL;
|
||||||
|
for ($i = 1; $i < 6; $i++) {
|
||||||
|
echo "Key $i exists? ", dba_exists("key$i", $db_file) ? "Y" : "N", \PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace second key data
|
||||||
|
dba_replace("key2", "Content 2 replaced", $db_file);
|
||||||
|
echo dba_fetch("key2", $db_file), \PHP_EOL;
|
||||||
|
|
||||||
|
// Close handler
|
||||||
|
dba_close($db_file);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
$db_filename = __DIR__ . '/data.mdb';
|
||||||
|
$db_loc_filename = __DIR__ . '/lock.mdb';
|
||||||
|
@unlink($db_filename);
|
||||||
|
@unlink($db_loc_filename);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
dba_open(): Argument #6 ($flags) must be either DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR for LMDB driver
|
||||||
|
key2: Content String 2
|
||||||
|
key4: Another Content String
|
||||||
|
key5: The last content string
|
||||||
|
Total keys: 3
|
||||||
|
Key 1 exists? N
|
||||||
|
Key 2 exists? Y
|
||||||
|
Key 3 exists? N
|
||||||
|
Key 4 exists? Y
|
||||||
|
Key 5 exists? Y
|
||||||
|
Content 2 replaced
|
Loading…
Add table
Add a link
Reference in a new issue