Skip to content

Commit e4f8239

Browse files
committed
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
1 parent aa9fb08 commit e4f8239

File tree

9 files changed

+162
-9
lines changed

9 files changed

+162
-9
lines changed

UPGRADING

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ PHP 8.2 UPGRADE NOTES
165165

166166
- DBA
167167
. dba_open() and dba_popen() now have the following enforced function signature
168-
dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0)
168+
dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null)
169169
. dba_fetch()'s optional skip argument is now at the end in line with
170170
PHP userland semantics its signature now is:
171171
dba_fetch(string|array $key, $dba, int $skip = 0): string|false
@@ -174,6 +174,7 @@ PHP 8.2 UPGRADE NOTES
174174
is still accepted, but it is recommended to use the new standard variant.
175175
- LMDB
176176
. When opened with the readonly mode, the MDB_RDONLY flag is now passed to the underlying database environment
177+
. The LMDB now accepts either the DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR for the dba_open() $flags parameter.
177178

178179
========================================
179180
6. New Functions

ext/dba/dba.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ PHP_MINIT_FUNCTION(dba)
359359
REGISTER_INI_ENTRIES();
360360
le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
361361
le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
362+
register_dba_symbols(module_number);
362363
return SUCCESS;
363364
}
364365
/* }}} */
@@ -478,10 +479,12 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
478479
zend_string *handler_str = NULL;
479480
zend_long permission = 0644;
480481
zend_long map_size = 0;
482+
zend_long driver_flags = DBA_DEFAULT_DRIVER_FLAGS;
483+
bool is_flags_null = true;
481484
zend_string *persistent_resource_key = NULL;
482485

483-
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!ll", &path, &mode, &handler_str,
484-
&permission, &map_size)) {
486+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "PS|S!lll!", &path, &mode, &handler_str,
487+
&permission, &map_size, &driver_flags, &is_flags_null)) {
485488
RETURN_THROWS();
486489
}
487490

@@ -503,6 +506,11 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
503506
RETURN_THROWS();
504507
}
505508

509+
if (!is_flags_null && driver_flags < 0) {
510+
zend_argument_value_error(6, "must be greater or equal than 0");
511+
RETURN_THROWS();
512+
}
513+
506514
if (persistent) {
507515
zend_resource *le;
508516

@@ -720,6 +728,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
720728
info->mode = modenr;
721729
info->file_permission = permission;
722730
info->map_size = map_size;
731+
info->driver_flags = driver_flags;
723732
info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
724733
info->lock.mode = lock_mode;
725734

@@ -835,9 +844,12 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent)
835844
}
836845
}
837846

838-
if (error || hptr->open(info, &error) != SUCCESS) {
847+
if (error || hptr->open(info, &error) == FAILURE) {
839848
dba_close(info);
840-
php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
849+
if (EXPECTED(!EG(exception))) {
850+
php_error_docref(NULL, E_WARNING, "Driver initialization failed for handler: %s%s%s",
851+
hptr->name, error?": ":"", error?error:"");
852+
}
841853
FREE_PERSISTENT_RESOURCE_KEY();
842854
RETURN_FALSE;
843855
}

ext/dba/dba.stub.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,21 @@
22

33
/** @generate-class-entries */
44

5+
#ifdef DBA_LMDB
6+
/** @var int */
7+
const DBA_LMDB_USE_SUB_DIR = 0;
8+
/**
9+
* @var int
10+
* @cname MDB_NOSUBDIR
11+
*/
12+
const DBA_LMDB_NO_SUB_DIR = UNKNOWN;
13+
#endif
14+
515
/** @return resource|false */
6-
function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) {}
16+
function dba_popen(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {}
717

818
/** @return resource|false */
9-
function dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0) {}
19+
function dba_open(string $path, string $mode, ?string $handler = null, int $permission = 0o644, int $map_size = 0, ?int $flags = null) {}
1020

1121
/** @param resource $dba */
1222
function dba_close($dba): void {}

ext/dba/dba_arginfo.h

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/dba/dba_lmdb.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,28 @@ DBA_OPEN_FUNC(lmdb)
4040
{
4141
MDB_env *env;
4242
MDB_txn *txn;
43-
int rc, flags = MDB_NOSUBDIR;
43+
int rc;
4444
int mode = info->file_permission;
4545
zend_long map_size = info->map_size;
4646

4747
ZEND_ASSERT(map_size >= 0);
4848

49+
/* By default use the MDB_NOSUBDIR flag */
50+
int flags = MDB_NOSUBDIR;
51+
/* Use flags passed by the user for driver flags */
52+
if (info->driver_flags != DBA_DEFAULT_DRIVER_FLAGS) {
53+
ZEND_ASSERT(info->driver_flags >= 0);
54+
switch (info->driver_flags) {
55+
case 0:
56+
case MDB_NOSUBDIR:
57+
flags = info->driver_flags;
58+
break;
59+
default:
60+
zend_argument_value_error(6, "must be either DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR for LMDB driver");
61+
return FAILURE;
62+
}
63+
}
64+
4965
/* Add readonly flag if DB is opened in read only mode */
5066
if (info->mode == DBA_READER) {
5167
flags |= MDB_RDONLY;
@@ -67,6 +83,7 @@ DBA_OPEN_FUNC(lmdb)
6783

6884
rc = mdb_env_open(env, info->path, flags, mode);
6985
if (rc) {
86+
mdb_env_close(env);
7087
*error = mdb_strerror(rc);
7188
return FAILURE;
7289
}

ext/dba/php_dba.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,16 @@ typedef struct dba_info {
4444
int fd;
4545
int file_permission;
4646
zend_long map_size;
47+
/* -1 for default driver flags */
48+
zend_long driver_flags;
4749
/* private */
4850
int flags; /* whether and how dba did locking and other flags*/
4951
struct dba_handler *hnd;
5052
dba_lock lock;
5153
} dba_info;
5254

55+
#define DBA_DEFAULT_DRIVER_FLAGS -1
56+
5357
#define DBA_LOCK_READER (0x0001)
5458
#define DBA_LOCK_WRITER (0x0002)
5559
#define DBA_LOCK_CREAT (0x0004)

ext/dba/php_lmdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifdef DBA_LMDB
55

66
#include "php_dba.h"
7+
#include <lmdb.h>
78

89
DBA_FUNCS(lmdb);
910

ext/dba/tests/dba_flags_arg.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
DBA new flags ValueError test
3+
--EXTENSIONS--
4+
dba
5+
--FILE--
6+
<?php
7+
try {
8+
dba_open('irrelevant', 'c', 'handler', flags: -1);
9+
} catch (\ValueError $e) {
10+
echo $e->getMessage(), \PHP_EOL;
11+
}
12+
?>
13+
--EXPECT--
14+
dba_open(): Argument #6 ($flags) must be greater or equal than 0

ext/dba/tests/dba_lmdb_flags.phpt

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
--TEST--
2+
DBA LMDB handler flags test
3+
--EXTENSIONS--
4+
dba
5+
--SKIPIF--
6+
<?php
7+
$handler = 'lmdb';
8+
require_once __DIR__ .'/skipif.inc';
9+
?>
10+
--FILE--
11+
<?php
12+
$handler = 'lmdb';
13+
14+
// Pass bogus flag
15+
try {
16+
$db_file = dba_open('irrelevant', 'c', $handler, flags: 45);
17+
} catch (\ValueError $e) {
18+
echo $e->getMessage(), \PHP_EOL;
19+
}
20+
21+
// Create DB with non-existent folder
22+
$db_filename = __DIR__ . '/lmdb-sub-dir.dbm';
23+
$db_file = dba_open($db_filename, 'c', $handler, flags: DBA_LMDB_USE_SUB_DIR);
24+
assert($db_file === false);
25+
26+
// Use current test folder
27+
$db_filename = __DIR__;
28+
$db_file = dba_open($db_filename, 'c', $handler, flags: DBA_LMDB_USE_SUB_DIR);
29+
assert($db_file !== false);
30+
31+
// Check insertion of data
32+
dba_insert("key1", "Content String 1", $db_file);
33+
dba_insert("key2", "Content String 2", $db_file);
34+
dba_insert("key3", "Third Content String", $db_file);
35+
dba_insert("key4", "Another Content String", $db_file);
36+
dba_insert("key5", "The last content string", $db_file);
37+
38+
// Remove some data
39+
dba_delete("key3", $db_file);
40+
dba_delete("key1", $db_file);
41+
42+
// Fetch data
43+
$key = dba_firstkey($db_file);
44+
$total_keys = 0;
45+
while ($key) {
46+
echo $key, ': ', dba_fetch($key, $db_file), \PHP_EOL;
47+
$key = dba_nextkey($db_file);
48+
$total_keys++;
49+
}
50+
echo 'Total keys: ', $total_keys, \PHP_EOL;
51+
for ($i = 1; $i < 6; $i++) {
52+
echo "Key $i exists? ", dba_exists("key$i", $db_file) ? "Y" : "N", \PHP_EOL;
53+
}
54+
55+
// Replace second key data
56+
dba_replace("key2", "Content 2 replaced", $db_file);
57+
echo dba_fetch("key2", $db_file), \PHP_EOL;
58+
59+
// Close handler
60+
dba_close($db_file);
61+
62+
?>
63+
--CLEAN--
64+
<?php
65+
$db_filename = __DIR__ . '/data.mdb';
66+
$db_loc_filename = __DIR__ . '/lock.mdb';
67+
@unlink($db_filename);
68+
@unlink($db_loc_filename);
69+
?>
70+
--EXPECTF--
71+
dba_open(): Argument #6 ($flags) must be either DBA_LMDB_USE_SUB_DIR or DBA_LMDB_NO_SUB_DIR for LMDB driver
72+
73+
Warning: dba_open(): Driver initialization failed for handler: lmdb: No such file or directory in %s on line %d
74+
key2: Content String 2
75+
key4: Another Content String
76+
key5: The last content string
77+
Total keys: 3
78+
Key 1 exists? N
79+
Key 2 exists? Y
80+
Key 3 exists? N
81+
Key 4 exists? Y
82+
Key 5 exists? Y
83+
Content 2 replaced

0 commit comments

Comments
 (0)