LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - clients.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 279 564 49.5 %
Date: 2024-04-25 20:03:45 Functions: 18 32 56.2 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * author Martin Kersten, Fabian Groffen
      15             :  * Client Management
      16             :  * Each online client is represented with an entry in the clients table.
      17             :  * The client may inspect his record at run-time and partially change its properties.
      18             :  * The administrator sees all client records and has the right to adjust global properties.
      19             :  */
      20             : 
      21             : 
      22             : #include "monetdb_config.h"
      23             : #include "clients.h"
      24             : #include "mcrypt.h"
      25             : #include "mal_scenario.h"
      26             : #include "mal_instruction.h"
      27             : #include "mal_runtime.h"
      28             : #include "mal_client.h"
      29             : #include "mal_authorize.h"
      30             : #include "mal_internal.h"
      31             : #include "opt_pipes.h"
      32             : #include "gdk_time.h"
      33             : 
      34             : static str
      35           1 : CLTsetListing(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      36             : {
      37           1 :         (void) mb;
      38           1 :         *getArgReference_int(stk, pci, 0) = cntxt->listing;
      39           1 :         cntxt->listing = *getArgReference_int(stk, pci, 1);
      40           1 :         return MAL_SUCCEED;
      41             : }
      42             : 
      43             : static str
      44           1 : CLTgetClientId(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      45             : {
      46           1 :         (void) mb;
      47           1 :         if (cntxt - mal_clients < 0 || cntxt - mal_clients >= MAL_MAXCLIENTS)
      48           0 :                 throw(MAL, "clients.getClientId", "Illegal client index");
      49           1 :         *getArgReference_int(stk, pci, 0) = (int) (cntxt - mal_clients);
      50           1 :         return MAL_SUCCEED;
      51             : }
      52             : 
      53             : static str
      54           0 : CLTgetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      55             : {
      56           0 :         (void) mb;
      57           0 :         if (cntxt->scenario)
      58           0 :                 *getArgReference_str(stk, pci, 0) = GDKstrdup(cntxt->scenario);
      59             :         else
      60           0 :                 *getArgReference_str(stk, pci, 0) = GDKstrdup("nil");
      61           0 :         if (*getArgReference_str(stk, pci, 0) == NULL)
      62           0 :                 throw(MAL, "clients.getScenario", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      63             :         return MAL_SUCCEED;
      64             : }
      65             : 
      66             : static str
      67           0 : CLTsetScenario(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      68             : {
      69           0 :         str msg = MAL_SUCCEED;
      70             : 
      71           0 :         (void) mb;
      72           0 :         msg = setScenario(cntxt, *getArgReference_str(stk, pci, 1));
      73           0 :         *getArgReference_str(stk, pci, 0) = 0;
      74           0 :         if (msg == NULL) {
      75           0 :                 *getArgReference_str(stk, pci, 0) = GDKstrdup(cntxt->scenario);
      76           0 :                 if (*getArgReference_str(stk, pci, 0) == NULL)
      77           0 :                         throw(MAL, "clients.setScenario", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      78             :         }
      79             :         return msg;
      80             : }
      81             : 
      82             : static void
      83           1 : CLTtimeConvert(time_t l, char *s)
      84             : {
      85           1 :         struct tm localt = (struct tm) { 0 };
      86             : 
      87           1 :         (void) localtime_r(&l, &localt);
      88             : 
      89             : #ifdef HAVE_ASCTIME_R3
      90             :         asctime_r(&localt, s, 26);
      91             : #else
      92           1 :         asctime_r(&localt, s);
      93             : #endif
      94           1 :         s[24] = 0;                                      /* remove newline */
      95           1 : }
      96             : 
      97             : static str
      98           1 : CLTInfo(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      99             : {
     100           1 :         bat *ret = getArgReference_bat(stk, pci, 0);
     101           1 :         bat *ret2 = getArgReference_bat(stk, pci, 1);
     102           1 :         BAT *b = COLnew(0, TYPE_str, 12, TRANSIENT);
     103           1 :         BAT *bn = COLnew(0, TYPE_str, 12, TRANSIENT);
     104           1 :         char buf[32];                           /* 32 bytes are enough */
     105             : 
     106           1 :         (void) mb;
     107           1 :         if (b == 0 || bn == 0) {
     108           0 :                 BBPreclaim(b);
     109           0 :                 BBPreclaim(bn);
     110           0 :                 throw(MAL, "clients.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     111             :         }
     112             : 
     113           1 :         (void) snprintf(buf, sizeof(buf), "" LLFMT "", (lng) cntxt->user);
     114           2 :         if (BUNappend(b, "user", false) != GDK_SUCCEED ||
     115           1 :                 BUNappend(bn, buf, false) != GDK_SUCCEED)
     116           0 :                 goto bailout;
     117             : 
     118           2 :         if (BUNappend(b, "scenario", false) != GDK_SUCCEED ||
     119           1 :                 BUNappend(bn, cntxt->scenario, false) != GDK_SUCCEED)
     120           0 :                 goto bailout;
     121             : 
     122           1 :         (void) snprintf(buf, sizeof(buf), "%d", cntxt->listing);
     123           2 :         if (BUNappend(b, "listing", false) != GDK_SUCCEED ||
     124           1 :                 BUNappend(bn, buf, false) != GDK_SUCCEED)
     125           0 :                 goto bailout;
     126             : 
     127           1 :         CLTtimeConvert(cntxt->login, buf);
     128           2 :         if (BUNappend(b, "login", false) != GDK_SUCCEED ||
     129           1 :                 BUNappend(bn, buf, false) != GDK_SUCCEED)
     130           0 :                 goto bailout;
     131           1 :         *ret = b->batCacheid;
     132           1 :         BBPkeepref(b);
     133           1 :         *ret2 = bn->batCacheid;
     134           1 :         BBPkeepref(bn);
     135           1 :         return MAL_SUCCEED;
     136             : 
     137           0 :   bailout:
     138           0 :         BBPunfix(b->batCacheid);
     139           0 :         BBPunfix(bn->batCacheid);
     140           0 :         throw(MAL, "clients.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     141             : }
     142             : 
     143             : static str
     144           0 : CLTLogin(bat *nme, bat *ret)
     145             : {
     146           0 :         BAT *b = COLnew(0, TYPE_str, 12, TRANSIENT);
     147           0 :         BAT *u = COLnew(0, TYPE_oid, 12, TRANSIENT);
     148           0 :         int i;
     149           0 :         char s[32];
     150             : 
     151           0 :         if (b == 0 || u == 0)
     152           0 :                 goto bailout;
     153             : 
     154           0 :         for (i = 0; i < MAL_MAXCLIENTS; i++) {
     155           0 :                 Client c = mal_clients + i;
     156           0 :                 if (c->mode >= RUNCLIENT && !is_oid_nil(c->user)) {
     157           0 :                         CLTtimeConvert(c->login, s);
     158           0 :                         if (BUNappend(b, s, false) != GDK_SUCCEED ||
     159           0 :                                 BUNappend(u, &c->user, false) != GDK_SUCCEED)
     160           0 :                                 goto bailout;
     161             :                 }
     162             :         }
     163           0 :         *ret = b->batCacheid;
     164           0 :         BBPkeepref(b);
     165           0 :         *nme = u->batCacheid;
     166           0 :         BBPkeepref(u);
     167           0 :         return MAL_SUCCEED;
     168             : 
     169           0 :   bailout:
     170           0 :         BBPreclaim(b);
     171           0 :         BBPreclaim(u);
     172           0 :         throw(MAL, "clients.getLogins", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     173             : }
     174             : 
     175             : static str
     176           1 : CLTquit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     177             : {
     178           1 :         str msg = MAL_SUCCEED;
     179           1 :         int idx = cntxt->idx;
     180           1 :         (void) mb;                                      /* fool compiler */
     181             : 
     182           1 :         if (pci->argc == 2) {
     183           0 :                 if (cntxt->user == MAL_ADMIN)
     184           0 :                         idx = *getArgReference_int(stk, pci, 1);
     185             :                 else
     186           0 :                         throw(MAL, "clients.quit",
     187             :                                   SQLSTATE(42000) "Administrator rights required");
     188             :         }
     189             : 
     190           1 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     191           0 :                 throw(MAL, "clients.quit", "Illegal session id");
     192             : 
     193             :         /* A user can only quit a session under the same id */
     194           1 :         MT_lock_set(&mal_contextLock);
     195           1 :         if (mal_clients[idx].mode == FREECLIENT)
     196           0 :                 msg = createException(MAL, "clients.stop",
     197             :                                                           "Session not active anymore");
     198             :         else
     199           1 :                 mal_clients[idx].mode = FINISHCLIENT;
     200           1 :         MT_lock_unset(&mal_contextLock);
     201           1 :         return msg;
     202             : }
     203             : 
     204             : /* Stopping a client in a soft manner by setting the time out marker */
     205             : static str
     206           0 : CLTstop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     207             : {
     208           0 :         int idx = cntxt->idx;
     209           0 :         str msg = MAL_SUCCEED;
     210             : 
     211           0 :         (void) mb;
     212           0 :         if (cntxt->user != MAL_ADMIN)
     213           0 :                 throw(MAL, "clients.stop",
     214             :                           SQLSTATE(42000) "Administrator rights required");
     215             : 
     216           0 :         idx = *getArgReference_int(stk, pci, 1);
     217             : 
     218           0 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     219           0 :                 throw(MAL, "clients.stop", "Illegal session id");
     220             : 
     221           0 :         MT_lock_set(&mal_contextLock);
     222           0 :         if (mal_clients[idx].mode == FREECLIENT)
     223           0 :                 msg = createException(MAL, "clients.stop",
     224             :                                                           "Session not active anymore");
     225             :         else
     226           0 :                 mal_clients[idx].qryctx.querytimeout = 1;       /* stop client in one microsecond */
     227             :         /* this forces the designated client to stop at the next instruction */
     228           0 :         MT_lock_unset(&mal_contextLock);
     229           0 :         return msg;
     230             : }
     231             : 
     232             : static str
     233           4 : CLTsetoptimizer(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     234             : {
     235           4 :         int idx = cntxt->idx;
     236           4 :         str opt, msg = MAL_SUCCEED;
     237             : 
     238           4 :         (void) mb;
     239           4 :         if (pci->argc == 3) {
     240           0 :                 if (cntxt->user == MAL_ADMIN) {
     241           0 :                         idx = *getArgReference_int(stk, pci, 1);
     242           0 :                         opt = *getArgReference_str(stk, pci, 2);
     243             :                 } else {
     244           0 :                         throw(MAL, "clients.setoptimizer",
     245             :                                   SQLSTATE(42000) "Administrator rights required");
     246             :                 }
     247             :         } else {
     248           4 :                 opt = *getArgReference_str(stk, pci, 1);
     249             :         }
     250             : 
     251           4 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     252           0 :                 throw(MAL, "clients.setoptimizer", "Illegal session id");
     253           4 :         if (strNil(opt))
     254           0 :                  throw(MAL, "clients.setoptimizer", "Input string cannot be NULL");
     255           4 :         if (strlen(opt) >= sizeof(mal_clients[idx].optimizer))
     256           0 :                  throw(MAL, "clients.setoptimizer", "Input string is too large");
     257           4 :         if (!isOptimizerPipe(opt))
     258           1 :                  throw(MAL, "clients.setoptimizer", "Valid optimizer pipe expected");
     259             : 
     260           3 :         MT_lock_set(&mal_contextLock);
     261           3 :         if (mal_clients[idx].mode == FREECLIENT)
     262           0 :                 msg = createException(MAL, "clients.setoptimizer",
     263             :                                                           "Session not active anymore");
     264             :         else
     265           3 :                 strcpy_len(mal_clients[idx].optimizer, opt,
     266             :                                    sizeof(mal_clients[idx].optimizer));
     267           3 :         MT_lock_unset(&mal_contextLock);
     268           3 :         return msg;
     269             : }
     270             : 
     271             : static str
     272           4 : CLTsetworkerlimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     273             : {
     274           4 :         str msg = MAL_SUCCEED;
     275           4 :         int idx = cntxt->idx, limit;
     276             : 
     277           4 :         (void) mb;
     278           4 :         if (pci->argc == 3) {
     279           0 :                 if (cntxt->user == MAL_ADMIN) {
     280           0 :                         idx = *getArgReference_int(stk, pci, 1);
     281           0 :                         limit = *getArgReference_int(stk, pci, 2);
     282             :                 } else {
     283           0 :                         throw(MAL, "clients.setworkerlimit",
     284             :                                   SQLSTATE(42000) "Administrator rights required");
     285             :                 }
     286             :         } else {
     287           4 :                 limit = *getArgReference_int(stk, pci, 1);
     288             :         }
     289             : 
     290           4 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     291           0 :                 throw(MAL, "clients.setworkerlimit", "Illegal session id");
     292           4 :         if (is_int_nil(limit))
     293           0 :                 throw(MAL, "clients.setworkerlimit",
     294             :                           "The number of workers cannot be NULL");
     295           4 :         if (limit < 0)
     296           1 :                 throw(MAL, "clients.setworkerlimit",
     297             :                           "The number of workers cannot be negative");
     298             : 
     299           3 :         MT_lock_set(&mal_contextLock);
     300           3 :         if (mal_clients[idx].mode == FREECLIENT)
     301           0 :                 msg = createException(MAL, "clients.setworkerlimit",
     302             :                                                           "Session not active anymore");
     303             :         else {
     304           3 :                 if (limit == 0) {
     305           0 :                         if (mal_clients[idx].maxworkers > 0)
     306             :                                 limit = mal_clients[idx].maxworkers;
     307           3 :                 } else if (cntxt->user != MAL_ADMIN &&
     308           0 :                                    mal_clients[idx].maxworkers > 0 &&
     309             :                                    mal_clients[idx].maxworkers < limit) {
     310           3 :                         limit = mal_clients[idx].maxworkers;
     311             :                 }
     312           3 :                 mal_clients[idx].workerlimit = limit;
     313             :         }
     314           3 :         MT_lock_unset(&mal_contextLock);
     315           3 :         return msg;
     316             : }
     317             : 
     318             : static str
     319           0 : CLTsetmemorylimit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     320             : {
     321           0 :         str msg = MAL_SUCCEED;
     322           0 :         int idx = cntxt->idx, limit;
     323             : 
     324           0 :         (void) mb;
     325           0 :         if (pci->argc == 3) {
     326           0 :                 if (cntxt->user == MAL_ADMIN) {
     327           0 :                         idx = *getArgReference_sht(stk, pci, 1);
     328           0 :                         limit = *getArgReference_int(stk, pci, 2);
     329             :                 } else {
     330           0 :                         throw(MAL, "clients.setmemorylimit",
     331             :                                   SQLSTATE(42000) "Administrator rights required");
     332             :                 }
     333             :         } else {
     334           0 :                 limit = *getArgReference_int(stk, pci, 1);
     335             :         }
     336             : 
     337           0 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     338           0 :                 throw(MAL, "clients.setmemorylimit", "Illegal session id");
     339           0 :         if (is_int_nil(limit))
     340           0 :                 throw(MAL, "clients.setmemorylimit",
     341             :                           "The memmory limit cannot be NULL");
     342           0 :         if (limit < 0)
     343           0 :                 throw(MAL, "clients.setmemorylimit",
     344             :                           "The memmory limit cannot be negative");
     345             : 
     346           0 :         lng mlimit = (lng) limit << 20;
     347             : 
     348           0 :         MT_lock_set(&mal_contextLock);
     349           0 :         if (mal_clients[idx].mode == FREECLIENT)
     350           0 :                 msg = createException(MAL, "clients.setmemorylimit",
     351             :                                                           "Session not active anymore");
     352             :         else {
     353           0 :                 if (mlimit == 0) {
     354           0 :                         if (mal_clients[idx].maxmem > 0)
     355             :                                 mlimit = mal_clients[idx].maxmem;
     356           0 :                 } else if (cntxt->user != MAL_ADMIN &&
     357           0 :                                    mal_clients[idx].maxmem > 0 &&
     358             :                                    mal_clients[idx].maxmem < mlimit) {
     359           0 :                         mlimit = mal_clients[idx].maxmem;
     360             :                 }
     361           0 :                 mal_clients[idx].memorylimit = (int) (mlimit >> 20);
     362           0 :                 mal_clients[idx].qryctx.maxmem = (ATOMIC_BASE_TYPE) mlimit;
     363             :         }
     364           0 :         MT_lock_unset(&mal_contextLock);
     365           0 :         return msg;
     366             : }
     367             : 
     368             : static str
     369           0 : CLTstopSession(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     370             : {
     371           0 :         str msg = MAL_SUCCEED;
     372           0 :         int idx = cntxt->idx;
     373           0 :         (void) mb;
     374             : 
     375           0 :         if (cntxt->user != MAL_ADMIN) {
     376           0 :                 throw(MAL, "clients.stopsession",
     377             :                           SQLSTATE(42000) "Administrator rights required");
     378             :         }
     379           0 :         idx = *getArgReference_int(stk, pci, 1);
     380           0 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     381           0 :                 throw(MAL, "clients.stopSession", "Illegal session id");
     382             : 
     383           0 :         MT_lock_set(&mal_contextLock);
     384           0 :         if (mal_clients[idx].mode == FREECLIENT) {
     385           0 :                 msg = createException(MAL, "clients.stopSession",
     386             :                                                           "Session not active anymore");
     387             :         } else {
     388           0 :                 mal_clients[idx].qryctx.querytimeout = 1;       /* stop client in one microsecond */
     389           0 :                 mal_clients[idx].sessiontimeout = 1;    /* stop client session */
     390             :         }
     391           0 :         MT_lock_unset(&mal_contextLock);
     392             :         /* this forces the designated client to stop at the next instruction */
     393           0 :         return msg;
     394             : }
     395             : 
     396             : /* Queries can be temporarily suspended */
     397             : static str
     398           0 : CLTsuspend(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     399             : {
     400           0 :         str msg = MAL_SUCCEED;
     401           0 :         int idx = cntxt->idx;
     402             : 
     403           0 :         if (cntxt->user != MAL_ADMIN)
     404           0 :                 throw(MAL, "clients.suspend",
     405             :                           SQLSTATE(42000) "Administrator rights required");
     406             : 
     407           0 :         idx = *getArgReference_int(stk, pci, 1);
     408           0 :         (void) mb;
     409             : 
     410           0 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     411           0 :                 throw(MAL, "clients.suspend", "Illegal session id");
     412             : 
     413           0 :         MT_lock_set(&mal_contextLock);
     414           0 :         if (mal_clients[idx].mode == FREECLIENT)
     415           0 :                 msg = createException(MAL, "clients.suspend",
     416             :                                                           "Session not active anymore");
     417             :         else
     418           0 :                 msg = MCsuspendClient(idx);
     419           0 :         MT_lock_unset(&mal_contextLock);
     420           0 :         return msg;
     421             : }
     422             : 
     423             : static str
     424           0 : CLTwakeup(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     425             : {
     426           0 :         str msg = MAL_SUCCEED;
     427           0 :         int idx = cntxt->idx;
     428             : 
     429           0 :         if (cntxt->user != MAL_ADMIN)
     430           0 :                 throw(MAL, "clients.wakeup",
     431             :                           SQLSTATE(42000) "Administrator rights required");
     432             : 
     433           0 :         idx = *getArgReference_int(stk, pci, 1);
     434           0 :         (void) mb;
     435             : 
     436           0 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     437           0 :                 throw(MAL, "clients.wakeup", "Illegal session id");
     438             : 
     439           0 :         MT_lock_set(&mal_contextLock);
     440           0 :         if (mal_clients[idx].mode == FREECLIENT)
     441           0 :                 msg = createException(MAL, "clients.wakeup",
     442             :                                                           "Session not active anymore");
     443             :         else
     444           0 :                 msg = MCawakeClient(idx);
     445           0 :         MT_lock_unset(&mal_contextLock);
     446           0 :         return msg;
     447             : }
     448             : 
     449             : /* set query timeout based in seconds, converted into microseconds */
     450             : static str
     451          19 : CLTqueryTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     452             : {
     453          19 :         str msg = MAL_SUCCEED;
     454          19 :         int qto, idx = cntxt->idx;
     455          19 :         (void) mb;
     456             : 
     457          19 :         if (pci->argc == 3) {
     458           0 :                 if (cntxt->user == MAL_ADMIN) {
     459           0 :                         idx = *getArgReference_int(stk, pci, 1);
     460           0 :                         qto = *getArgReference_int(stk, pci, 2);
     461             :                 } else {
     462           0 :                         throw(MAL, "clients.setquerytimeout",
     463             :                                   SQLSTATE(42000) "Administrator rights required");
     464             :                 }
     465             :         } else {
     466          19 :                 qto = *getArgReference_int(stk, pci, 1);
     467             :         }
     468          19 :         if (is_int_nil(qto))
     469           0 :                 throw(MAL, "clients.setquerytimeout", "Query timeout cannot be NULL");
     470          19 :         if (qto < 0)
     471           1 :                 throw(MAL, "clients.setquerytimeout", "Query timeout should be >= 0");
     472             : 
     473          18 :         MT_lock_set(&mal_contextLock);
     474          18 :         if (mal_clients[idx].mode == FREECLIENT)
     475           0 :                 msg = createException(MAL, "clients.setquerytimeout",
     476             :                                                           "Session not active anymore");
     477             :         else {
     478             :                 /* when testing (FORCEMITOMASK), reduce timeout of 1 sec to 1 msec */
     479          36 :                 lng timeout_micro = ATOMIC_GET(&GDKdebug) & FORCEMITOMASK
     480          18 :                                 && qto == 1 ? 1000 : (lng) qto * 1000000;
     481          18 :                 mal_clients[idx].qryctx.querytimeout = timeout_micro;
     482          18 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     483          18 :                 if (qry_ctx)
     484          18 :                         qry_ctx->querytimeout = timeout_micro;
     485             :         }
     486          18 :         MT_lock_unset(&mal_contextLock);
     487          18 :         return msg;
     488             : }
     489             : 
     490             : // set query timeout based in microseconds
     491             : static str
     492           2 : CLTqueryTimeoutMicro(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     493             : {
     494           2 :         str msg = MAL_SUCCEED;
     495           2 :         int idx = cntxt->idx;
     496           2 :         lng qto = *getArgReference_lng(stk, pci, 1);
     497           2 :         (void) mb;
     498             : 
     499           2 :         if (is_lng_nil(qto))
     500           0 :                 throw(MAL, "clients.queryTimeout", "Query timeout cannot be NULL");
     501           2 :         if (qto < 0)
     502           0 :                 throw(MAL, "clients.queryTimeout", "Query timeout should be >= 0");
     503             : 
     504           2 :         MT_lock_set(&mal_contextLock);
     505           2 :         if (mal_clients[idx].mode == FREECLIENT)
     506           0 :                 msg = createException(MAL, "clients.queryTimeout",
     507             :                                                           "Session not active anymore");
     508             :         else {
     509           2 :                 mal_clients[idx].qryctx.querytimeout = qto;
     510           2 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     511           2 :                 if (qry_ctx)
     512           2 :                         qry_ctx->querytimeout = qto;
     513             :         }
     514           2 :         MT_lock_unset(&mal_contextLock);
     515           2 :         return msg;
     516             : }
     517             : 
     518             : /* Set the current session timeout in seconds */
     519             : static str
     520        2690 : CLTsessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     521             : {
     522        2690 :         str msg = MAL_SUCCEED;
     523        2690 :         int sto = -1, idx = cntxt->idx;
     524        2690 :         (void) mb;
     525             : 
     526        2690 :         if (pci->argc == 3) {
     527           0 :                 if (cntxt->user == MAL_ADMIN) {
     528           0 :                         idx = *getArgReference_int(stk, pci, 1);
     529           0 :                         sto = *getArgReference_int(stk, pci, 2);
     530             :                 } else {
     531           0 :                         throw(MAL, "clients.setsessiontimeout",
     532             :                                   SQLSTATE(42000) "Administrator rights required");
     533             :                 }
     534             :         } else {
     535        2690 :                 sto = *getArgReference_int(stk, pci, 1);
     536             :         }
     537        2690 :         if (is_int_nil(sto))
     538           0 :                 throw(MAL, "clients.setsessiontimeout",
     539             :                           "Session timeout cannot be NULL");
     540        2690 :         if (sto < 0)
     541           1 :                 throw(MAL, "clients.setsessiontimeout",
     542             :                           "Session timeout should be >= 0");
     543        2689 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     544           0 :                 throw(MAL, "clients.setsessiontimeout", "Illegal session id %d", idx);
     545             : 
     546        2689 :         MT_lock_set(&mal_contextLock);
     547        2689 :         if (mal_clients[idx].mode == FREECLIENT)
     548           0 :                 msg = createException(MAL, "clients.setsessiontimeout",
     549             :                                                           "Session not active anymore");
     550             :         else {
     551        2689 :                 mal_clients[idx].sessiontimeout = sto > 0 ? (lng) sto *1000000 + (GDKusec() - mal_clients[idx].session) : 0;
     552        2689 :                 mal_clients[idx].logical_sessiontimeout = (lng) sto;
     553             :         }
     554        2689 :         MT_lock_unset(&mal_contextLock);
     555        2689 :         return msg;
     556             : }
     557             : 
     558             : /* Retrieve the session time out */
     559             : static str
     560           0 : CLTgetProfile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     561             : {
     562           0 :         str *opt = getArgReference_str(stk, pci, 0);
     563           0 :         int *qto = getArgReference_int(stk, pci, 1);
     564           0 :         int *sto = getArgReference_int(stk, pci, 2);
     565           0 :         int *wlim = getArgReference_int(stk, pci, 3);
     566           0 :         int *mlim = getArgReference_int(stk, pci, 4);
     567           0 :         (void) mb;
     568           0 :         if (!(*opt = GDKstrdup(cntxt->optimizer)))
     569           0 :                 throw(MAL, "clients.getProfile", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     570           0 :         *qto = (int) (cntxt->qryctx.querytimeout / 1000000);
     571           0 :         *sto = (int) (cntxt->sessiontimeout / 1000000);
     572           0 :         *wlim = cntxt->workerlimit;
     573           0 :         *mlim = cntxt->memorylimit;
     574           0 :         return MAL_SUCCEED;
     575             : }
     576             : 
     577             : /* Long running queries are traced in the logger
     578             :  * with a message from the interpreter.
     579             :  * This value should be set to minutes to avoid a lengthly log */
     580             : static str
     581           0 : CLTsetPrintTimeout(void *ret, int *secs)
     582             : {
     583           0 :         (void) ret;
     584           0 :         if (is_int_nil(*secs))
     585           0 :                 setqptimeout(0);
     586             :         else
     587           0 :                 setqptimeout((lng) *secs * 60 * 1000000);
     588           0 :         return MAL_SUCCEED;
     589             : }
     590             : 
     591             : static str
     592          14 : CLTmd5sum(str *ret, str *pw)
     593             : {
     594          14 :         if (strNil(*pw)) {
     595           1 :                 *ret = GDKstrdup(str_nil);
     596             :         } else {
     597          13 :                 char *mret = mcrypt_MD5Sum(*pw, strlen(*pw));
     598             : 
     599          13 :                 if (!mret)
     600           0 :                         throw(MAL, "clients.md5sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     601          13 :                 *ret = GDKstrdup(mret);
     602          13 :                 free(mret);
     603             :         }
     604          14 :         if (*ret == NULL)
     605           0 :                 throw(MAL, "clients.md5sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     606             :         return MAL_SUCCEED;
     607             : }
     608             : 
     609             : static str
     610           1 : CLTsha1sum(str *ret, str *pw)
     611             : {
     612           1 :         if (strNil(*pw)) {
     613           0 :                 *ret = GDKstrdup(str_nil);
     614             :         } else {
     615           1 :                 char *mret = mcrypt_SHA1Sum(*pw, strlen(*pw));
     616             : 
     617           1 :                 if (!mret)
     618           0 :                         throw(MAL, "clients.sha1sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     619           1 :                 *ret = GDKstrdup(mret);
     620           1 :                 free(mret);
     621             :         }
     622           1 :         if (*ret == NULL)
     623           0 :                 throw(MAL, "clients.sha1sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     624             :         return MAL_SUCCEED;
     625             : }
     626             : 
     627             : static str
     628           1 : CLTripemd160sum(str *ret, str *pw)
     629             : {
     630           1 :         if (strNil(*pw)) {
     631           0 :                 *ret = GDKstrdup(str_nil);
     632             :         } else {
     633           1 :                 char *mret = mcrypt_RIPEMD160Sum(*pw, strlen(*pw));
     634             : 
     635           1 :                 if (!mret)
     636           0 :                         throw(MAL, "clients.ripemd160sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     637           1 :                 *ret = GDKstrdup(mret);
     638           1 :                 free(mret);
     639             :         }
     640           1 :         if (*ret == NULL)
     641           0 :                 throw(MAL, "clients.ripemd160sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     642             :         return MAL_SUCCEED;
     643             : }
     644             : 
     645             : static str
     646           4 : CLTsha2sum(str *ret, str *pw, int *bits)
     647             : {
     648           8 :         if (strNil(*pw) || is_int_nil(*bits)) {
     649           0 :                 *ret = GDKstrdup(str_nil);
     650             :         } else {
     651           4 :                 char *mret = 0;
     652           4 :                 switch (*bits) {
     653           1 :                 case 512:
     654           1 :                         mret = mcrypt_SHA512Sum(*pw, strlen(*pw));
     655           1 :                         break;
     656           1 :                 case 384:
     657           1 :                         mret = mcrypt_SHA384Sum(*pw, strlen(*pw));
     658           1 :                         break;
     659           1 :                 case 256:
     660           1 :                         mret = mcrypt_SHA256Sum(*pw, strlen(*pw));
     661           1 :                         break;
     662           1 :                 case 224:
     663           1 :                         mret = mcrypt_SHA224Sum(*pw, strlen(*pw));
     664           1 :                         break;
     665           0 :                 default:
     666           0 :                         (void) mret;
     667           0 :                         throw(ILLARG, "clients.sha2sum", "wrong number of bits "
     668             :                                   "for SHA2 sum: %d", *bits);
     669             :                 }
     670           4 :                 if (!mret)
     671           0 :                         throw(MAL, "clients.sha2sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     672           4 :                 *ret = GDKstrdup(mret);
     673           4 :                 free(mret);
     674             :         }
     675           4 :         if (*ret == NULL)
     676           0 :                 throw(MAL, "clients.sha2sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     677             :         return MAL_SUCCEED;
     678             : }
     679             : 
     680             : static str
     681           0 : CLTbackendsum(str *ret, str *pw)
     682             : {
     683           0 :         if (strNil(*pw)) {
     684           0 :                 *ret = GDKstrdup(str_nil);
     685             :         } else {
     686           0 :                 char *mret = mcrypt_BackendSum(*pw, strlen(*pw));
     687           0 :                 if (mret == NULL)
     688           0 :                         throw(MAL, "clients.backendsum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     689           0 :                 *ret = GDKstrdup(mret);
     690           0 :                 free(mret);
     691             :         }
     692           0 :         if (*ret == NULL)
     693           0 :                 throw(MAL, "clients.backendsum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     694             :         return MAL_SUCCEED;
     695             : }
     696             : 
     697             : static str
     698           5 : CLTgetUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     699             : {
     700           5 :         str *ret = getArgReference_str(stk, pci, 0);
     701           5 :         (void) mb;
     702             : 
     703           5 :         *ret = GDKstrdup(cntxt->username);
     704           5 :         return MAL_SUCCEED;
     705             : }
     706             : 
     707             : static str
     708           0 : CLTgetPasswordHash(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     709             : {
     710           0 :         (void) cntxt;
     711           0 :         (void) mb;
     712           0 :         (void) stk;
     713           0 :         (void) pci;
     714             : 
     715           0 :         throw(MAL, "clients.getPassword",
     716             :                   SQLSTATE(0A000) PROGRAM_NYI);
     717             : }
     718             : 
     719             : static str
     720           0 : CLTcheckPermission(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     721             : {
     722           0 :         (void) cntxt;
     723           0 :         (void) mb;
     724           0 :         (void) stk;
     725           0 :         (void) pci;
     726             : 
     727           0 :         throw(MAL, "clients.checkPermission",
     728             :                   SQLSTATE(0A000) PROGRAM_NYI);
     729             : }
     730             : 
     731             : str
     732           2 : CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     733             : {
     734           2 :         str *ret = getArgReference_str(stk, pci, 0);
     735           2 :         int delay;
     736           2 :         bit force = FALSE;
     737           2 :         int leftover;
     738           2 :         char buf[1024] = { "safe to stop last connection" };
     739             : 
     740           2 :         if (pci->argc == 3)
     741           1 :                 force = *getArgReference_bit(stk, pci, 2);
     742             : 
     743           2 :         (void) mb;
     744             : 
     745           2 :         delay = *getArgReference_bte(stk, pci, 1);
     746             : 
     747           2 :         if (cntxt->user != MAL_ADMIN)
     748           0 :                 throw(MAL, "mal.shutdown",
     749             :                           SQLSTATE(42000) "Administrator rights required");
     750           2 :         if (is_int_nil(delay))
     751             :                 throw(MAL, "mal.shutdown", "Delay cannot be NULL");
     752           2 :         if (delay < 0)
     753           0 :                 throw(MAL, "mal.shutdown", "Delay cannot be negative");
     754           2 :         if (is_bit_nil(force))
     755           0 :                 throw(MAL, "mal.shutdown", "Force cannot be NULL");
     756           2 :         MCstopClients(cntxt);
     757           2 :         do {
     758           2 :                 if ((leftover = MCactiveClients() - 1))
     759           0 :                         MT_sleep_ms(1000);
     760           2 :                 delay--;
     761           2 :         } while (delay > 0 && leftover > 1);
     762           2 :         if (delay == 0 && leftover > 1)
     763           0 :                 snprintf(buf, 1024, "%d client sessions still running", leftover);
     764           2 :         *ret = GDKstrdup(buf);
     765           2 :         if (force)
     766           1 :                 GDKprepareExit();
     767           2 :         if (*ret == NULL)
     768           0 :                 throw(MAL, "mal.shutdown", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     769             :         return MAL_SUCCEED;
     770             : }
     771             : 
     772             : str
     773          26 : CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     774             : {
     775          26 :         BAT *id = NULL, *user = NULL, *login = NULL, *sessiontimeout = NULL,
     776          26 :                 *querytimeout = NULL, *idle = NULL;
     777          26 :         BAT *opt = NULL, *wlimit = NULL, *mlimit = NULL;
     778          26 :         bat *idId = getArgReference_bat(stk, pci, 0);
     779          26 :         bat *userId = getArgReference_bat(stk, pci, 1);
     780          26 :         bat *loginId = getArgReference_bat(stk, pci, 2);
     781          26 :         bat *idleId = getArgReference_bat(stk, pci, 3);
     782          26 :         bat *optId = getArgReference_bat(stk, pci, 4);
     783          26 :         bat *sessiontimeoutId = getArgReference_bat(stk, pci, 5);
     784          26 :         bat *querytimeoutId = getArgReference_bat(stk, pci, 6);
     785          26 :         bat *wlimitId = getArgReference_bat(stk, pci, 7);
     786          26 :         bat *mlimitId = getArgReference_bat(stk, pci, 8);
     787          26 :         Client c;
     788          26 :         timestamp ret;
     789          26 :         int timeout;
     790          26 :         str msg = NULL;
     791             : 
     792          26 :         (void) cntxt;
     793          26 :         (void) mb;
     794             : 
     795          26 :         id = COLnew(0, TYPE_int, 0, TRANSIENT);
     796          26 :         user = COLnew(0, TYPE_str, 0, TRANSIENT);
     797          26 :         login = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
     798          26 :         opt = COLnew(0, TYPE_str, 0, TRANSIENT);
     799          26 :         sessiontimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
     800          26 :         querytimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
     801          26 :         wlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
     802          26 :         mlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
     803          26 :         idle = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
     804             : 
     805          26 :         if (id == NULL || user == NULL || login == NULL || sessiontimeout == NULL
     806          26 :                 || idle == NULL || querytimeout == NULL || opt == NULL || wlimit == NULL
     807          26 :                 || mlimit == NULL) {
     808           0 :                 BBPreclaim(id);
     809           0 :                 BBPreclaim(user);
     810           0 :                 BBPreclaim(login);
     811           0 :                 BBPreclaim(sessiontimeout);
     812           0 :                 BBPreclaim(querytimeout);
     813           0 :                 BBPreclaim(idle);
     814             : 
     815           0 :                 BBPreclaim(opt);
     816           0 :                 BBPreclaim(wlimit);
     817           0 :                 BBPreclaim(mlimit);
     818           0 :                 throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     819             :         }
     820             : 
     821          26 :         MT_lock_set(&mal_contextLock);
     822             : 
     823        1690 :         for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
     824        1664 :                 if (c->mode == RUNCLIENT) {
     825          26 :                         const char *username = c->username;
     826          26 :                         if (!username)
     827           0 :                                 username = str_nil;
     828          26 :                         if (BUNappend(user, username, false) != GDK_SUCCEED)
     829           0 :                                 goto bailout;
     830          26 :                         ret = timestamp_fromtime(c->login);
     831          26 :                         if (is_timestamp_nil(ret)) {
     832           0 :                                 msg = createException(SQL, "sql.sessions",
     833             :                                                                           SQLSTATE(22003)
     834             :                                                                           "Failed to convert user logged time");
     835           0 :                                 goto bailout;
     836             :                         }
     837          26 :                         if (BUNappend(id, &c->idx, false) != GDK_SUCCEED)
     838           0 :                                  goto bailout;
     839          26 :                         if (BUNappend(login, &ret, false) != GDK_SUCCEED)
     840           0 :                                 goto bailout;
     841          26 :                         timeout = (int) (c->logical_sessiontimeout);
     842          26 :                         if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED)
     843           0 :                                 goto bailout;
     844          26 :                         timeout = (int) (c->qryctx.querytimeout / 1000000);
     845          26 :                         if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED)
     846           0 :                                 goto bailout;
     847          26 :                         if (c->idle) {
     848           0 :                                 ret = timestamp_fromtime(c->idle);
     849           0 :                                 if (is_timestamp_nil(ret)) {
     850           0 :                                         msg = createException(SQL, "sql.sessions",
     851             :                                                                                   SQLSTATE(22003)
     852             :                                                                                   "Failed to convert user logged time");
     853           0 :                                         goto bailout;
     854             :                                 }
     855             :                         } else
     856          26 :                                 ret = timestamp_nil;
     857          26 :                         if (BUNappend(idle, &ret, false) != GDK_SUCCEED)
     858           0 :                                 goto bailout;
     859          26 :                         if (BUNappend(opt, &c->optimizer, false) != GDK_SUCCEED)
     860           0 :                                  goto bailout;
     861          26 :                         if (BUNappend(wlimit, &c->workerlimit, false) != GDK_SUCCEED)
     862           0 :                                 goto bailout;
     863          26 :                         if (BUNappend(mlimit, &c->memorylimit, false) != GDK_SUCCEED)
     864           0 :                                 goto bailout;
     865             :                 }
     866             :         }
     867          26 :         MT_lock_unset(&mal_contextLock);
     868          26 :         *idId = id->batCacheid;
     869          26 :         BBPkeepref(id);
     870          26 :         *userId = user->batCacheid;
     871          26 :         BBPkeepref(user);
     872          26 :         *loginId = login->batCacheid;
     873          26 :         BBPkeepref(login);
     874          26 :         *sessiontimeoutId = sessiontimeout->batCacheid;
     875          26 :         BBPkeepref(sessiontimeout);
     876          26 :         *querytimeoutId = querytimeout->batCacheid;
     877          26 :         BBPkeepref(querytimeout);
     878          26 :         *idleId = idle->batCacheid;
     879          26 :         BBPkeepref(idle);
     880             : 
     881          26 :         *optId = opt->batCacheid;
     882          26 :         BBPkeepref(opt);
     883          26 :         *wlimitId = wlimit->batCacheid;
     884          26 :         BBPkeepref(wlimit);
     885          26 :         *mlimitId = mlimit->batCacheid;
     886          26 :         BBPkeepref(mlimit);
     887          26 :         return MAL_SUCCEED;
     888             : 
     889           0 :   bailout:
     890           0 :         MT_lock_unset(&mal_contextLock);
     891           0 :         BBPunfix(id->batCacheid);
     892           0 :         BBPunfix(user->batCacheid);
     893           0 :         BBPunfix(login->batCacheid);
     894           0 :         BBPunfix(sessiontimeout->batCacheid);
     895           0 :         BBPunfix(querytimeout->batCacheid);
     896           0 :         BBPunfix(idle->batCacheid);
     897             : 
     898           0 :         BBPunfix(opt->batCacheid);
     899           0 :         BBPunfix(wlimit->batCacheid);
     900           0 :         BBPunfix(mlimit->batCacheid);
     901           0 :         return msg;
     902             : }
     903             : 
     904             : static str
     905           0 : CLTgetSessionID(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     906             : {
     907           0 :         (void) mb;
     908           0 :         (void) stk;
     909           0 :         (void) pci;
     910           0 :         *getArgReference_int(stk, pci, 0) = cntxt->idx;
     911           0 :         return MAL_SUCCEED;
     912             : }
     913             : 
     914             : #include "mel.h"
     915             : mel_func clients_init_funcs[] = {
     916             :  pattern("clients", "setListing", CLTsetListing, true, "Turn on/off echo of MAL instructions:\n1 - echo input,\n2 - show mal instruction,\n4 - show details of type resolutoin, \n8 - show binding information.", args(1,2, arg("",int),arg("flag",int))),
     917             :  pattern("clients", "getId", CLTgetClientId, false, "Return a number that uniquely represents the current client.", args(1,1, arg("",int))),
     918             :  pattern("clients", "getInfo", CLTInfo, false, "Pseudo bat with client attributes.", args(2,2, batarg("",str),batarg("",str))),
     919             :  pattern("clients", "getScenario", CLTgetScenario, false, "Retrieve current scenario name.", args(1,1, arg("",str))),
     920             :  pattern("clients", "setScenario", CLTsetScenario, true, "Switch to other scenario handler, return previous one.", args(1,2, arg("",str),arg("msg",str))),
     921             :  pattern("clients", "quit", CLTquit, true, "Terminate the client session.", args(1,1, arg("",void))),
     922             :  pattern("clients", "quit", CLTquit, true, "Terminate the session for a single client using a soft error.\nIt is the privilege of the console user.", args(1,2, arg("",void),arg("idx",int))),
     923             :  command("clients", "getLogins", CLTLogin, false, "Pseudo bat of client id and login time.", args(2,2, batarg("user",oid),batarg("start",str))),
     924             :  pattern("clients", "stop", CLTstop, true, "Stop the query execution at the next eligble statement.", args(0,1, arg("id",int))),
     925             :  pattern("clients", "suspend", CLTsuspend, true, "Put a client process to sleep for some time.\nIt will simple sleep for a second at a time, until\nthe awake bit has been set in its descriptor", args(1,2, arg("",void),arg("id",int))),
     926             :  pattern("clients", "wakeup", CLTwakeup, true, "Wakeup a client process", args(1,2, arg("",void),arg("id",int))),
     927             :  pattern("clients", "getprofile", CLTgetProfile, false, "Retrieve the profile settings for a client", args(5,5, arg("opt",str),arg("q",int),arg("s",int),arg("w",int),arg("m",int))),
     928             :  pattern("clients", "setQryTimeoutMicro", CLTqueryTimeoutMicro, true, "", args(1,2, arg("",void),arg("n",lng))),
     929             :  pattern("clients", "setquerytimeout", CLTqueryTimeout, true, "", args(1,2, arg("",void),arg("n",int))),
     930             :  pattern("clients", "setquerytimeout", CLTqueryTimeout, true, "A query is aborted after q seconds (q=0 means run undisturbed).", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     931             :  pattern("clients", "setsessiontimeout", CLTsessionTimeout, true, "", args(1,2, arg("",void),arg("n",int))),
     932             :  pattern("clients", "setsessiontimeout", CLTsessionTimeout, true, "Set the session timeout for a particulat session id", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     933             :  pattern("clients", "setoptimizer", CLTsetoptimizer, true, "", args(1,2, arg("",void),arg("opt",str))),
     934             :  pattern("clients", "setoptimizer", CLTsetoptimizer, true, "Set the session optimizer", args(1,3, arg("",void),arg("sid",int),arg("opt",str))),
     935             :  pattern("clients", "setworkerlimit", CLTsetworkerlimit, true, "", args(1,2, arg("",void),arg("n",int))),
     936             :  pattern("clients", "setworkerlimit", CLTsetworkerlimit, true, "Limit the number of worker threads per query", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     937             :  pattern("clients", "setmemorylimit", CLTsetmemorylimit, true, "", args(1,2, arg("",void),arg("n",int))),
     938             :  pattern("clients", "setmemorylimit", CLTsetmemorylimit, true, "Limit the memory claim in MB per query", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     939             :  pattern("clients", "stopsession", CLTstopSession, true, "Stop a particular session", args(1,2, arg("",void),arg("sid",int))),
     940             :  command("clients", "setprinttimeout", CLTsetPrintTimeout, true, "Print running query every so many seconds.", args(1,2, arg("",void),arg("n",int))),
     941             :  pattern("clients", "shutdown", CLTshutdown, true, "", args(1,2, arg("",str),arg("delay",bte))),
     942             :  pattern("clients", "shutdown", CLTshutdown, true, "Close all other client connections. Return if it succeeds.\nIf forced is set then always stop the system the hard way", args(1,3, arg("",str),arg("delay",bte),arg("forced",bit))),
     943             :  command("clients", "md5sum", CLTmd5sum, false, "Return hex string representation of the MD5 hash of the given string", args(1,2, arg("",str),arg("pw",str))),
     944             :  command("clients", "sha1sum", CLTsha1sum, false, "Return hex string representation of the SHA-1 hash of the given string", args(1,2, arg("",str),arg("pw",str))),
     945             :  command("clients", "sha2sum", CLTsha2sum, false, "Return hex string representation of the SHA-2 hash with bits of the given string", args(1,3, arg("",str),arg("pw",str),arg("bits",int))),
     946             :  command("clients", "ripemd160sum", CLTripemd160sum, false, "Return hex string representation of the RIPEMD160 hash of the given string", args(1,2, arg("",str),arg("pw",str))),
     947             :  command("clients", "backendsum", CLTbackendsum, false, "Return hex string representation of the currently used hash of the given string", args(1,2, arg("",str),arg("pw",str))),
     948             :  pattern("clients", "getUsername", CLTgetUsername, false, "Return the username of the currently logged in user", args(1,1, arg("",str))),
     949             :  pattern("clients", "getPasswordHash", CLTgetPasswordHash, false, "Return the password hash of the given user", args(1,2, arg("",str),arg("user",str))),
     950             :  pattern("clients", "checkPermission", CLTcheckPermission, false, "Check permission for a user, requires hashed password (backendsum)", args(1,3, arg("",void),arg("usr",str),arg("pw",str))),
     951             :  pattern("clients", "current_sessionid", CLTgetSessionID, false, "return current session ID", args(1,1, arg("",int))),
     952             :  { .imp=NULL }
     953             : };
     954             : #include "mal_import.h"
     955             : #ifdef _MSC_VER
     956             : #undef read
     957             : #pragma section(".CRT$XCU",read)
     958             : #endif
     959         329 : LIB_STARTUP_FUNC(init_clients_mal)
     960         329 : { mal_module("clients", NULL, clients_init_funcs); }

Generated by: LCOV version 1.14