The other day i was struggeling with some strange behaviour, of two concurrently running scripts, that i want to share here. I am omitting most of the error handling for brevity.
script1:
$h = dba_open("file_a", 'r', 'gdbm');
while (true)
{
dba_fetch("somekey", $h);
sleep(1);
}
dba_close($h);
______________________
script2:
// while script1 is running until eternity...
$ok = rename("file_a", "file_b");
if (! $ok)
echo "Could not move\n";
else
echo "I like to move it, move it!\n";
// GOAL: Manipulate the file only if it is not opened for reading...
RESULT:
I like to move it, move it!
So you can very well rename a file, while it is opened. The lookup in script1 is still working. Manipulating the file in script2 will fail, as there is still an gdbm lock on the file from script1.
dba_open
(PHP 4, PHP 5)
dba_open — Ouvre une base de données DBA
Description
dba_open() établit une connexion à
la base repérée par path avec le
mode mode et l'identifiant
handler.
Liste de paramètres
-
path -
Chemin sur votre système de fichiers.
-
mode -
Il vaut r pour lecture seule, w pour lecture/écriture, c pour lecture/écriture, et création si la base n'existe pas, et n pour création, écrasement et accès en lecture/écriture. La base de données est créé en mode BTree ; les autres modes (comme Hash ou Queue) ne sont pas supportés.
De plus, vous pouvez choisir la méthode de verrouillage de la base avec le caractère suivant. Utilisez l pour verrouiller la base avec un fichier .lck, ou d pour verrouiller la base elle-même. Il est important que vos application utilisent ces options de manière cohérente.
Si vous voulez tester la possibilité d'accès, et ne pas attendre la disponibilité du verrou, vous pouvez ajouter la lettre t comme troisième caractère. Lorsque vous êtes absolument certain que votre base ne requiert pas de verrou, vous pouvez utiliser le tiret - à la place de l ou d. Lorsque vous n'utilisez ni d, ni l ni -, dba va verrouiller en mode d.
Note:
Il ne peut y avoir qu'un seul type d'écriture dans la base. Lorsque vous utilisez dba sur un serveur web, et que plusieurs requêtes HTTP effectuent des écritures, elles ne peuvent être faites que l'une après l'autre. De même, la lecture durant l'écriture n'est pas possible. L'extension dba utilise un verrou pour éviter ces problèmes. Voici la table de verrouillage :
Verrouillage DBA déjà ouverte mode= "rl"mode= "rlt"mode= "wl"mode= "wlt"mode= "rd"mode= "rdt"mode= "wd"mode= "wdt"non-ouverte ok ok ok ok ok ok ok ok mode= "rl"ok ok attente FALSEillégal illégal illégal illégal mode= "wl"attente FALSEattente FALSEillégal illégal illégal illégal mode= "rd"illégal illégal illégal illégal ok ok attente FALSEmode= "wd"illégal illégal illégal illégal attente FALSEattente FALSE- ok: Le second appel réussit.
- wait: Le second appel attend que dba_close() soit appelé par le premier script.
FALSE: Le second appel retourneFALSE.- illégal: vous ne devez pas mélanger les options "l" et "d" pour le paramètre
mode.
-
handler -
Le nom du gestionnaire qui doit être utilisé pour accéder à
path. C'est passé à tous les paramètres facultatifs donnés à dba_open() et peut agir au nom d'eux.
Valeurs de retour
Retourne un gestionnaire positif en cas de succès ou FALSE si une erreur survient.
Historique
| Version | Description |
|---|---|
| 4.3.0 | il est possible d'ouvrir la base de données à travers le réseau. Toutefois, dans le cas où des connexions sockets seront utilisées (via HTTP ou FTP), la connexion sera verrouillée, et non pas la ressource. C'est important de le savoir pour comprendre que dans ce cas, le verrouillage sera ignoré, et d'autres solutions doivent être trouvées. |
| 4.3.0 |
Le paramètre de verrouillage mode et les options
"l", "d", "-" et "t" ont été ajoutées.
Dans les versions de PHP antérieures à la PHP 4.3.0, vous deviez
utiliser des sémaphores pour éviter les accès concurrents à la base
de données, hormis pour celles de type GDBM. Voyez le chapitre sur les
sémaphores System V.
|
| avant 4.3.5 | le mode "c" est inopérant pour de nombreux gestionnaires internes, et tronque la base au lieu d'ajouter les données à la base existante. De plus, dbm et ndbm échoue en mode "c" dans des configurations typiques (impossible à corriger). |
Voir aussi
- dba_popen() - Ouvre une connexion persistante à une base de données DBA
- dba_close() - Ferme une base DBA
Apache doesn't support Berkeley DB Btree, so you can't manipulate use db4 as the type of database if you want to do DBM authentication with Apache.
gdbm seemed to work fine though, even though it supposedly using Btree instead of hash. It makes you wonder why Apache would use hash for one dbmtype versus btree for another.
So since Apache and PHP don't have options to choose the method for the Berkeley DBs, you are out of luck.
Note the “c” create flag does not work if MySQL was built with the “cdb” DBA handler compile option which is common for many distros. By definition the cdb DBA handler is optimized for reading/writing and “no updates are allowed.”
<?php
$dbh = dba_open( "./data2/productz", "c", "cdb") or die( "Couldn't open Database" );
?>
instead use
<?php
$dbh = dba_open( "./data2/productz", "n", "cdb" ) or die( "Couldnt open Database" );
?>
generates this error message in the /var/log/apache2/error.log:
[Sun Sep 06 04:18:15 2009] [error] [client 192.168.1.125] PHP Warning: dba_open(./data2/productz,c) [<a href='function.dba-open'>function.dba-open</a>]: Driver initialization failed for handler: cdb: Update operations are not supported in /var/www/projects/testcdb-c.php on line 43
see user contributed comment under dba_handlers() to see which DBA handlers are supported by your build of MySQL and note about using “cdb” compiled DBA systems:
also see user contributed comment under dba_replace() about incompatibilities with cdb DBA handler compiled MySQL systems.
As of GDBM version 1.8.3, GDBM's underlying open call uses non-blocking calls to flock() on systems that have flock(). As a result, calls with "rd" or "wd" locking modes will return error ("Can't be reader" or "Can't be writer") instead of waiting. Use "rl" or "wl" instead, to make PHP do its own locking external to GDBM.
Here's a simple example to use the dba_open function
<?php
$id = dba_open("/tmp/test.db", "n", "gdbm");
if (!$id) {
echo "dba_open failed\n";
exit;
}
dba_replace("key", "This is an example!", $id);
if (dba_exists("key", $id)) {
echo dba_fetch("key", $id);
dba_delete("key", $id);
}
dba_close($id);
?>
Windows does not support locking the database. You may use $_ENV to determine the OS:
$locking = (stripos($_ENV['OS'],'windows') === false ? 'd' : 'l');
If you get some strange errors like
dba_open(): myDbFilename.db : Permission denied
than you are propably using PHP on a Windoze machine. You have to make sure that the following conditions are met:
1) Use an absolute path to your db file. Relative paths will cause problems with locking
2) Specify a locking mode - that's the second character of the mode-argument, or else opening a dba-file will cause several notices/warnings etc.
And a final, general note:
3) Always use the english PHP doc on this site - the translations are often old as hell and miss important informations
HTH, Nils.
