Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] Closing descriptors in forked (pipe) command



On Sat, Feb 18, 2017, at 09:02 PM, Bart Schaefer wrote:
> You/we certainly may wish to document that it is dangerous to assume
> that parent and subshell can both manipulate the tied parameter, but
> it would be incorrect to automatically close the file descriptor in
> either of them.

I've updated docs and added "zgdbmclear" builtin as we now know GDBM is
fine with concurrent access if only it can be synchronized. In Zsh this
is possible via zsystem flock. I think PM_UPTODATE is a great feature as
no other program can change the database. With zsystem flock and
zgdbmclear, one can write a concurrent, elastic program within Zsh (a
challenge, though).

Also added a test case, but tests haven't been commited:

 ztie -d db/gdbm -f $dbfile dbase
 dbase[testkey]=value1
 fun() { while read line; do echo $line; done }
 eval "dbase[testkey]=value2" | fun
 echo $dbase[testkey]
 zgdbmclear dbase testkey
 echo $dbase[testkey]
0:Test store in forked Zsh
>value1
>value2

Best regards,
Sebastian Gniazdowski
diff --git a/Doc/Zsh/mod_db_gdbm.yo b/Doc/Zsh/mod_db_gdbm.yo
index 699e9ab..7063690 100644
--- a/Doc/Zsh/mod_db_gdbm.yo
+++ b/Doc/Zsh/mod_db_gdbm.yo
@@ -49,6 +49,15 @@ item(tt(zgdbmpath) var(parametername))(
 Put path to database file assigned to var(parametername) into tt(REPLY)
 scalar.
 )
+findex(zgdbmclear)
+cindex(database concurrent access)
+item(tt(zgdbmclear) var(parametername) var(keyname))(
+The tied database is enabled for concurrent access only within single Zsh
+instance. User must use tt(zsystem flock) to guard that access if it involves
+any writes. To refetch a key from database when its change in concurrent
+Zsh process is possible, user should use tt(zgdbmclear) passing name of
+database and name of the key to refetch.
+)
 findex(zgdbm_tied)
 cindex(database tied arrays, enumerating)
 item(tt(zgdbm_tied))(
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index 596a8ae..730abea 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -89,6 +89,7 @@ static struct builtin bintab[] = {
     BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:r", NULL),
     BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, "u", NULL),
     BUILTIN("zgdbmpath", 0, bin_zgdbmpath, 1, -1, 0, "", NULL),
+    BUILTIN("zgdbmclear", 0, bin_zgdbmclear, 2, -1, 0, "", NULL),
 };
 
 #define ROARRPARAMDEF(name, var) \
@@ -260,6 +261,42 @@ bin_zgdbmpath(char *nam, char **args, Options ops, UNUSED(int func))
     return 0;
 }
 
+/**/
+static int
+bin_zgdbmclear(char *nam, char **args, Options ops, UNUSED(int func))
+{
+    Param pm;
+    char *pmname, *key;
+
+    pmname = *args++;
+    key = *args;
+
+    if (!pmname) {
+        zwarnnam(nam, "parameter name (whose path is to be written to $REPLY) is required");
+        return 1;
+    }
+
+    pm = (Param) paramtab->getnode(paramtab, pmname);
+    if(!pm) {
+        zwarnnam(nam, "no such parameter: %s", pmname);
+        return 1;
+    }
+
+    if (pm->gsu.h != &gdbm_hash_gsu) {
+        zwarnnam(nam, "not a tied gdbm parameter: %s", pmname);
+        return 1;
+    }
+
+    HashTable ht = pm->u.hash;
+    HashNode hn = gethashnode2( ht, key );
+    Param val_pm = (Param) hn;
+    if (val_pm) {
+        val_pm->node.flags &= ~(PM_UPTODATE);
+    }
+
+    return 0;
+}
+
 /*
  * The param is actual param in hash â?? always, because
  * getgdbmnode creates every new key seen. However, it


Messages sorted by: Reverse Date, Date, Thread, Author