Changeset: 5eca024e0234 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5eca024e0234 Added Files: MonetDB5/modules/mal/Tests/inspect05.stable.out MonetDB5/modules/mal/clients.h Modified Files: MonetDB5/ChangeLog MonetDB5/modules/mal/clients.c MonetDB5/modules/mal/clients.mal MonetDB5/optimizer/opt_garbageCollector.c MonetDB5/optimizer/opt_mitosis.c clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 clients/Tests/exports.stable.out gdk/gdk_join.c sql/ChangeLog sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_upgrades.c sql/common/sql_types.c sql/scripts/22_clients.sql sql/server/rel_rel.h sql/server/rel_select.c sql/server/rel_select.h sql/test/BugTracker-2014/Tests/aggregates-intervals.Bug-3533.sql sql/test/BugTracker-2014/Tests/aggregates-intervals.Bug-3533.stable.err sql/test/BugTracker-2014/Tests/aggregates-intervals.Bug-3533.stable.out sql/test/BugTracker-2019/Tests/duplicates-not-eliminated-long-CASE-stmt.Bug-6697.stable.out.single sql/test/BugTracker/Tests/explain.SF-1739353.stable.out sql/test/BugTracker/Tests/jdbc_no_debug.SF-1739356.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-explain-2join-query.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-explain-2join-view.stable.out sql/test/emptydb-upgrade-chain-hge/Tests/package.py sql/test/emptydb-upgrade-chain/Tests/package.py sql/test/emptydb/Tests/check.stable.out sql/test/emptydb/Tests/check.stable.out.32bit sql/test/emptydb/Tests/check.stable.out.int128 sql/test/emptydb/Tests/package-hge.py sql/test/emptydb/Tests/package.py sql/test/sys-schema/Tests/systemfunctions.stable.out sql/test/sys-schema/Tests/systemfunctions.stable.out.int128 sql/test/testdb-upgrade-chain-hge/Tests/package.py sql/test/testdb-upgrade-chain/Tests/package.py sql/test/testdb/Tests/package-hge.py sql/test/testdb/Tests/package.py testing/Mtest.py.in Branch: gdk-tracer Log Message:
Merge branch 'branches/default' into branches/gdk-tracer diffs (truncated from 1385 to 300 lines): diff --git a/MonetDB5/ChangeLog b/MonetDB5/ChangeLog --- a/MonetDB5/ChangeLog +++ b/MonetDB5/ChangeLog @@ -1,6 +1,14 @@ # ChangeLog file for MonetDB5 # This file is updated with Maddlog +* Tue Nov 19 2019 Pedro Ferreira <pedro.ferre...@monetdbsolutions.com> +- Added session identifier, number of workers and memory claim to the + sysmon queue. +- The worker (number of threads), memory (in MB) and optimizer pipeline + limits can now be set per user session basis. The query and session + timeouts are now set in seconds. +- With required privileges an user can set resource limits for a session. + * Wed Nov 13 2019 Sjoerd Mullender <sjo...@acm.org> - There are now versions of group.(sub)group(done) that produce a single output containing just the groups. diff --git a/MonetDB5/modules/mal/Tests/inspect05.stable.out b/MonetDB5/modules/mal/Tests/inspect05.stable.out new file mode 100644 --- /dev/null +++ b/MonetDB5/modules/mal/Tests/inspect05.stable.out @@ -0,0 +1,106 @@ +stdout of test 'inspect05` in directory 'monetdb5/modules/mal` itself: + + +# 18:15:32 > +# 18:15:32 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "gdk_dbfarm=/home/sjoerd/Monet-devel/var/MonetDB" "--set" "mapi_open=true" "--set" "mapi_port=37682" "--set" "monet_prompt=" "--trace" "--forcemito" "--set" "mal_listing=2" "--dbname=mTests_modules_mal" "inspect05.mal" +# 18:15:32 > + +# MonetDB 5 server v11.10.0 (hg id: d6a857b5d084) +# This is an unreleased version +# Serving database 'mTests_modules_mal', using 2 threads +# Compiled for x86_64-unknown-linux-gnu/64bit with 64bit OIDs dynamically linked +# Found 3.861 GiB available main-memory. +# Copyright (c) 1993-July 2008 CWI. +# Copyright (c) August 2008-2015 MonetDB B.V., all rights reserved +# Visit http://www.monetdb.org/ for further information +# Listening for connection requests on mapi:monetdb://koolmees.mullender.nl:37682/ +# MonetDB/GIS module loaded +# MonetDB/JAQL module loaded +# MonetDB/SQL module loaded +# MonetDB/R module loaded + + +# 09:46:13 > +# 09:46:13 > "mclient" "-lmal" "-ftest" "-Eutf-8" "--host=/var/tmp/mtest-26774" "--port=35410" +# 09:46:13 > + +#--------------------------# +# t t t t t # name +# str str str str str # type +#--------------------------# +[ 0@0, "append", "command", "bat", "(i:bat[:any_1], u:any_1):bat[:any_1] ", "BKCappend_val_wrap;" ] +[ 1@0, "append", "command", "bat", "(tt:int, heapfile:str):bat[:any_1] ", "BKCattach;" ] +[ 2@0, "append", "command", "bat", "(i:bat[:any_1], u:any_1, force:bit):bat[:any_1] ", "BKCappend_val_force_wrap;" ] +[ 3@0, "append", "command", "bat", "(i:bat[:any_1], u:bat[:any_1], s:bat[:oid], force:bit):bat[:any_1] ", "BKCappend_cand_force_wrap;" ] +[ 4@0, "append", "command", "bat", "(i:bat[:any_1], u:bat[:any_1], s:bat[:oid]):bat[:any_1] ", "BKCappend_cand_wrap;" ] +[ 5@0, "append", "command", "bat", "(i:bat[:any_1], u:bat[:any_1], force:bit):bat[:any_1] ", "BKCappend_force_wrap;" ] +[ 6@0, "attach", "command", "bat", "(i:bat[:any_1], u:bat[:any_1]):bat[:any_1] ", "BKCappend_wrap;" ] +[ 7@0, "delete", "command", "bat", "(a:bat[:oid], b:bat[:oid]):bat[:oid] ", "BKCdiffcand;" ] +[ 8@0, "delete", "command", "bat", "(sz:lng):bat[:oid] ", "BKCdensebat;" ] +[ 9@0, "delete", "command", "bat", "(b:bat[:any_1]):bat[:any_1] ", "BKCdelete_all;" ] +[ 10@0, "densebat", "command", "bat", "(b:bat[:any_1], d:bat[:oid]):bat[:any_1] ", "BKCdelete_multi;" ] +[ 11@0, "diffcand", "command", "bat", "(b:bat[:any_1], h:oid):bat[:any_1] ", "BKCdelete;" ] +[ 12@0, "getAccess", "pattern", "bat", "(bv:bat[:any_1]):bat[:oid] ", "OIDXgetorderidx;" ] +[ 13@0, "getCapacity", "command", "bat", "(b:bat[:any_1]):str ", "BKCgetBBPname;" ] +[ 14@0, "getColumnType", "command", "bat", "(b:bat[:any_1]):oid ", "BKCgetSequenceBase;" ] +[ 15@0, "getName", "command", "bat", "(b:bat[:any_1]):str ", "BKCgetAccess;" ] +[ 16@0, "getRole", "command", "bat", "(bid:bat[:any_1]):str ", "BKCgetRole;" ] +[ 17@0, "getSequenceBase", "command", "bat", "(b:bat[:any_1]):str ", "BKCgetColumnType;" ] +[ 18@0, "getSize", "command", "bat", "(b:bat[:any_1]):lng ", "BKCgetCapacity;" ] +[ 19@0, "getorderidx", "command", "bat", "(b:bat[:any_1]):lng ", "BKCgetSize;" ] +[ 20@0, "hasorderidx", "pattern", "bat", "(bv:bat[:any_1]):bit ", "OIDXhasorderidx;" ] +[ 21@0, "imprints", "command", "bat", "(b:bat[:dbl]):lng ", "CMDBATimprintsize;" ] +[ 22@0, "imprints", "command", "bat", "(b:bat[:flt]):lng ", "CMDBATimprintsize;" ] +[ 23@0, "imprints", "command", "bat", "(b:bat[:lng]):lng ", "CMDBATimprintsize;" ] +[ 24@0, "imprints", "command", "bat", "(b:bat[:int]):lng ", "CMDBATimprintsize;" ] +[ 25@0, "imprints", "command", "bat", "(b:bat[:sht]):lng ", "CMDBATimprintsize;" ] +[ 26@0, "imprints", "command", "bat", "(b:bat[:bte]):lng ", "CMDBATimprintsize;" ] +[ 27@0, "imprintsize", "command", "bat", "(b:bat[:dbl]):void ", "CMDBATimprints;" ] +[ 28@0, "imprintsize", "command", "bat", "(b:bat[:flt]):void ", "CMDBATimprints;" ] +[ 29@0, "imprintsize", "command", "bat", "(b:bat[:lng]):void ", "CMDBATimprints;" ] +[ 30@0, "imprintsize", "command", "bat", "(b:bat[:int]):void ", "CMDBATimprints;" ] +[ 31@0, "imprintsize", "command", "bat", "(b:bat[:sht]):void ", "CMDBATimprints;" ] +[ 32@0, "imprintsize", "command", "bat", "(b:bat[:bte]):void ", "CMDBATimprints;" ] +[ 33@0, "info", "command", "bat", "(a:bat[:oid], b:bat[:oid]):bat[:oid] ", "BKCintersectcand;" ] +[ 34@0, "intersectcand", "command", "bat", "(b1:bat[:any_1], b2:bat[:any_2]):bit ", "BKCisSynced;" ] +[ 35@0, "isPersistent", "command", "bat", "(b:bat[:any_1]):bit ", "BKCisPersistent;" ] +[ 36@0, "isSorted", "command", "bat", "(b:bat[:any_1]):bit ", "BKCisTransient;" ] +[ 37@0, "isSortedReverse", "command", "bat", "(b:bat[:any_1]):bit ", "BKCisSortedReverse;" ] +[ 38@0, "isSynced", "command", "bat", "(b:bat[:any_1]):bit ", "BKCisSorted;" ] +[ 39@0, "isTransient", "command", "bat", "(b:bat[:any_1]):bit ", "BKCgetKey;" ] +[ 40@0, "isaKey", "command", "bat", "(b:bat[:any_1]) (X_0:bat[:str], X_1:bat[:str]) ", "BKCinfo;" ] +[ 41@0, "mergecand", "command", "bat", "(a:bat[:oid], b:bat[:oid]):bat[:oid] ", "BKCmergecand;" ] +[ 42@0, "mirror", "command", "bat", "(b:bat[:any_2]):bat[:oid] ", "BKCmirror;" ] +[ 43@0, "new", "pattern", "bat", "(tt:any_1, size:lng):bat[:any_1] ", "CMDBATnew;" ] +[ 44@0, "new", "pattern", "bat", "(tt:any_1, size:int, persist:bit):bat[:any_1] ", "CMDBATnew;" ] +[ 45@0, "new", "pattern", "bat", "(tt:any_1, size:lng, persist:bit):bat[:any_1] ", "CMDBATnew;" ] +[ 46@0, "new", "pattern", "bat", "(tt:any_1, size:int):bat[:any_1] ", "CMDBATnew;" ] +[ 47@0, "new", "pattern", "bat", "(tt:any_1):bat[:any_1] ", "CMDBATnew;" ] +[ 48@0, "orderidx", "pattern", "bat", "(bv:bat[:any_1], l:bat[:any_1]...):void ", "OIDXmerge;" ] +[ 49@0, "orderidx", "pattern", "bat", "(bv:bat[:any_1], pieces:int):void ", "OIDXcreate;" ] +[ 50@0, "orderidx", "pattern", "bat", "(bv:bat[:any_1]):void ", "OIDXcreate;" ] +[ 51@0, "pack", "pattern", "bat", "(X_0:any_2...):bat[:any_2] ", "MATpackValues;" ] +[ 52@0, "partition", "pattern", "bat", "(b:bat[:any_1], pieces:int, n:int):bat[:any_1] ", "CMDBATpartition2;" ] +[ 53@0, "partition", "pattern", "bat", "(b:bat[:any_1]):bat[:any_1]... ", "CMDBATpartition;" ] +[ 54@0, "replace", "command", "bat", "(b:bat[:any_1], del:bat[:oid]):bat[:oid] ", "BKCreuseBATmap;" ] +[ 55@0, "replace", "command", "bat", "(b:bat[:any_1], del:bat[:oid]):bat[:any_1] ", "BKCreuseBAT;" ] +[ 56@0, "replace", "command", "bat", "(b:bat[:any_1], rid:bat[:oid], val:bat[:any_1], force:bit):bat[:any_1] ", "BKCbat_inplace_force;" ] +[ 57@0, "replace", "command", "bat", "(b:bat[:any_1], rid:bat[:oid], val:bat[:any_1]):bat[:any_1] ", "BKCbat_inplace;" ] +[ 58@0, "reuse", "command", "bat", "(b:bat[:any_1], h:oid, t:any_1, force:bit):bat[:any_1] ", "BKCbun_inplace_force;" ] +[ 59@0, "reuseMap", "command", "bat", "(b:bat[:any_1], h:oid, t:any_1):bat[:any_1] ", "BKCbun_inplace;" ] +[ 60@0, "save", "pattern", "bat", "(val:any_1):bat[:any_1] ", "CMDBATsingle;" ] +[ 61@0, "save", "command", "bat", "(b:bat[:any_1]):bit ", "BKCsetImprints;" ] +[ 62@0, "setAccess", "command", "bat", "(b:bat[:any_1]):bit ", "BKCsetHash;" ] +[ 63@0, "setColumn", "command", "bat", "(nme:str):bit ", "BKCsave;" ] +[ 64@0, "setHash", "command", "bat", "(nme:bat[:any_1]):void ", "BKCsave2;" ] +[ 65@0, "setImprints", "command", "bat", "(b:bat[:any_1]):void ", "BKCsetPersistent;" ] +[ 66@0, "setKey", "command", "bat", "(b:bat[:any_1]):void ", "BKCsetTransient;" ] +[ 67@0, "setName", "command", "bat", "(b:bat[:any_1], t:str):void ", "BKCsetColumn;" ] +[ 68@0, "setPersistent", "command", "bat", "(b:bat[:any_1], s:str):void ", "BKCsetName;" ] +[ 69@0, "setTransient", "command", "bat", "(b:bat[:any_1], mode:str):bat[:any_1] ", "BKCsetAccess;" ] +[ 70@0, "single", "command", "bat", "(b:bat[:any_1], mode:bit):bat[:any_1] ", "BKCsetkey;" ] + +# 08:55:30 > +# 08:55:30 > Done. +# 08:55:30 > + diff --git a/MonetDB5/modules/mal/clients.c b/MonetDB5/modules/mal/clients.c --- a/MonetDB5/modules/mal/clients.c +++ b/MonetDB5/modules/mal/clients.c @@ -364,6 +364,50 @@ CLTwakeup(void *ret, int *id) return MCawakeClient(*id); } +/* Set session time out based in seconds. As of December 2019, this function is deprecated */ +str +CLTsetSessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + lng sto; + int idx = cntxt->idx; + + (void) mb; + if( idx < 0 || idx > MAL_MAXCLIENTS) + throw(MAL,"clients.setsession","Illegal session id %d", idx); + if (mal_clients[idx].mode == FREECLIENT) + throw(MAL,"clients.setsession","Session not active anymore"); + sto = *getArgReference_lng(stk,pci,1); + if (sto < 0) + throw(MAL,"clients.setsession","Session timeout should be >= 0"); + mal_clients[idx].sessiontimeout = sto * 1000000; + return MAL_SUCCEED; +} + +/* Set the current query timeout in seconds. As of December 2019, this function is deprecated */ +str +CLTsetTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + lng qto,sto; + int idx = cntxt->idx; + + (void) mb; + if( idx < 0 || idx > MAL_MAXCLIENTS) + throw(MAL,"clients.settimeout","Illegal session id %d", idx); + if (mal_clients[idx].mode == FREECLIENT) + throw(MAL,"clients.settimeout","Session not active anymore"); + qto = *getArgReference_lng(stk,pci,1); + if (qto < 0) + throw(MAL,"clients.settimeout","Query timeout should be >= 0"); + if (pci->argc == 3) { + sto = *getArgReference_lng(stk,pci,2); + if( sto < 0) + throw(MAL,"clients.settimeout","Session timeout should be >= 0"); + mal_clients[idx].sessiontimeout = sto * 1000000; + } + mal_clients[idx].querytimeout = qto * 1000000; + return MAL_SUCCEED; +} + /* set session time out based in seconds, converted into microseconds */ str CLTqueryTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) diff --git a/MonetDB5/modules/mal/clients.h b/MonetDB5/modules/mal/clients.h new file mode 100644 --- /dev/null +++ b/MonetDB5/modules/mal/clients.h @@ -0,0 +1,57 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. + */ + +/* + * @+ Monet client data + * Portions of the client record can be directly obtained for + * backward compatibility. The routine clientInfo provides more + * detailed information. + */ +#ifndef _CLIENTS_H +#define _CLIENTS_H +#include "mal.h" +#include "mal_interpreter.h" + +mal_export str CLTsetListing(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetClientId(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTquit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTLogin(bat *ret, bat *nme); +mal_export str CLTInfo(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTstop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsuspend(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetSessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTqueryTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetoptimizer(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetworkerlimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetmemorylimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTstopSession(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetProfile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetPrintTimeout(void *ret, int *secs); +mal_export str CLTwakeup(void *ret, int *id); + +mal_export str CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTmd5sum(str *ret, str *pw); +mal_export str CLTsha1sum(str *ret, str *pw); +mal_export str CLTripemd160sum(str *ret, str *pw); +mal_export str CLTsha2sum(str *ret, str *pw, int *bits); +mal_export str CLTbackendsum(str *ret, str *pw); +mal_export str CLTaddUser(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTremoveUser(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetPasswordHash(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTchangeUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTchangePassword(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsetPassword(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTcheckPermission(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTgetUsers(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +mal_export str CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +#endif /* _CLIENTS_H */ diff --git a/MonetDB5/modules/mal/clients.mal b/MonetDB5/modules/mal/clients.mal --- a/MonetDB5/modules/mal/clients.mal +++ b/MonetDB5/modules/mal/clients.mal @@ -60,6 +60,22 @@ pattern getprofile()(opt:str, q:int, s:i address CLTgetProfile comment "Retrieve the profile settings for a client"; +# As of December 2019, the pattern setsession is deprecated, use setsessiontimeout +pattern setsession(n:lng):void +address CLTsetSessionTimeout +comment "Abort a session after n seconds."; + +# As of December 2019, the pattern settimeout is deprecated, use setquerytimeout +pattern settimeout(n:lng):void +address CLTsetTimeout +comment "Abort a query after n seconds."; + +pattern settimeout(q:lng,s:lng):void +address CLTsetTimeout +comment "Abort a query after q seconds (q=0 means run undisturbed). +The session timeout aborts the connection after spending too +many seconds on query processing."; + # set properties of others pattern setquerytimeout(n:int):void address CLTqueryTimeout; diff --git a/MonetDB5/optimizer/opt_garbageCollector.c b/MonetDB5/optimizer/opt_garbageCollector.c --- a/MonetDB5/optimizer/opt_garbageCollector.c +++ b/MonetDB5/optimizer/opt_garbageCollector.c @@ -65,8 +65,6 @@ OPTgarbageCollectorImplementation(Client for(i = 0; i < limit; i++) if(mb->stmt[i] && getModuleId(mb->stmt[i]) == querylogRef && getFunctionId(mb->stmt[i]) == defineRef ){ p = getInstrPtr(mb,i); - if( i != 1) - fprintf(stderr, "define statement not in expected place %d\n", i); break; } diff --git a/MonetDB5/optimizer/opt_mitosis.c b/MonetDB5/optimizer/opt_mitosis.c --- a/MonetDB5/optimizer/opt_mitosis.c +++ b/MonetDB5/optimizer/opt_mitosis.c @@ -11,23 +11,6 @@ #include "mal_interpreter.h" #include "gdk_utils.h" -static int -eligible(MalBlkPtr mb) -{ - InstrPtr p; - int i; - for (i = 1; i < mb->stop; i++) { - p = getInstrPtr(mb, i); - if (getModuleId(p) == sqlRef && getFunctionId(p) == assertRef && - p->argc > 2 && getArgType(mb, p, 2) == TYPE_str && - isVarConstant(mb, getArg(p, 2)) && _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list