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:
|
||||
. Fixed LMDB driver memory leak on DB creation failure (Girgias)
|
||||
. Fixed GH-8856 (dba: lmdb: allow to override the MDB_NOSUBDIR flag). (Girgias)
|
||||
|
||||
- Random:
|
||||
. 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.
|
||||
. 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:
|
||||
. Added an oci8.prefetch_lob_size directive and oci_set_prefetch_lob()
|
||||
function to tune LOB query performance by reducing the number of
|
||||
|
@ -183,7 +188,7 @@ PHP 8.2 UPGRADE NOTES
|
|||
|
||||
- DBA
|
||||
. 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
|
||||
PHP userland semantics its signature now is:
|
||||
dba_fetch(string|array $key, $dba, int $skip = 0): string|false
|
||||
|
|
|
@ -359,6 +359,7 @@ PHP_MINIT_FUNCTION(dba)
|
|||
REGISTER_INI_ENTRIES();
|
||||
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);
|
||||
register_dba_symbols(module_number);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -478,10 +479,12 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
|||
zend_string *handler_str = NULL;
|
||||
zend_long permission = 0644;
|
||||
zend_long map_size = 0;
|
||||
zend_long driver_flags = DBA_DEFAULT_DRIVER_FLAGS;
|
||||
bool is_flags_null = true;
|
||||
zend_string *persistent_resource_key = NULL;
|
||||
|
||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!ll", &path, &mode, &handler_str,
|
||||
&permission, &map_size)) {
|
||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!lll!", &path, &mode, &handler_str,
|
||||
&permission, &map_size, &driver_flags, &is_flags_null)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
|
@ -503,6 +506,11 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
|||
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) {
|
||||
zend_resource *le;
|
||||
|
||||
|
@ -720,6 +728,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
|
|||
info->mode = modenr;
|
||||
info->file_permission = permission;
|
||||
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->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);
|
||||
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();
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,21 @@
|
|||
|
||||
/** @generate-class-entries */
|
||||
|
||||
/** @return resource|false */
|
||||
function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) {}
|
||||
#ifdef DBA_LMDB
|
||||
/** @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 */
|
||||
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 */
|
||||
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.
|
||||
* Stub hash: 1957dd08c4efcfa765bd15c8d9ae9e69edec5db5 */
|
||||
* Stub hash: 1a02eaf9da45edb40720620e3beef43fd19dd520 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
|
||||
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, 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, flags, IS_LONG, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#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_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_txn *txn;
|
||||
int rc, flags = MDB_NOSUBDIR;
|
||||
int rc;
|
||||
int mode = info->file_permission;
|
||||
zend_long map_size = info->map_size;
|
||||
|
||||
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 */
|
||||
if (info->mode == DBA_READER) {
|
||||
flags |= MDB_RDONLY;
|
||||
|
|
|
@ -44,12 +44,16 @@ typedef struct dba_info {
|
|||
int fd;
|
||||
int file_permission;
|
||||
zend_long map_size;
|
||||
/* -1 for default driver flags */
|
||||
zend_long driver_flags;
|
||||
/* private */
|
||||
int flags; /* whether and how dba did locking and other flags*/
|
||||
struct dba_handler *hnd;
|
||||
dba_lock lock;
|
||||
} dba_info;
|
||||
|
||||
#define DBA_DEFAULT_DRIVER_FLAGS -1
|
||||
|
||||
#define DBA_LOCK_READER (0x0001)
|
||||
#define DBA_LOCK_WRITER (0x0002)
|
||||
#define DBA_LOCK_CREAT (0x0004)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#ifdef DBA_LMDB
|
||||
|
||||
#include "php_dba.h"
|
||||
#include <lmdb.h>
|
||||
|
||||
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