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-26 00:35:57 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.endtime = 1;    /* stop client now */
     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.endtime = 1;    /* stop client now */
     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].querytimeout = timeout_micro;
     482          18 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     483          18 :                 if (qry_ctx) {
     484          18 :                         qry_ctx->endtime = qry_ctx->starttime && timeout_micro ? qry_ctx->starttime + timeout_micro : 0;
     485             :                 }
     486             :         }
     487          18 :         MT_lock_unset(&mal_contextLock);
     488          18 :         return msg;
     489             : }
     490             : 
     491             : // set query timeout based in microseconds
     492             : static str
     493           2 : CLTqueryTimeoutMicro(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     494             : {
     495           2 :         str msg = MAL_SUCCEED;
     496           2 :         int idx = cntxt->idx;
     497           2 :         lng qto = *getArgReference_lng(stk, pci, 1);
     498           2 :         (void) mb;
     499             : 
     500           2 :         if (is_lng_nil(qto))
     501           0 :                 throw(MAL, "clients.queryTimeout", "Query timeout cannot be NULL");
     502           2 :         if (qto < 0)
     503           0 :                 throw(MAL, "clients.queryTimeout", "Query timeout should be >= 0");
     504             : 
     505           2 :         MT_lock_set(&mal_contextLock);
     506           2 :         if (mal_clients[idx].mode == FREECLIENT)
     507           0 :                 msg = createException(MAL, "clients.queryTimeout",
     508             :                                                           "Session not active anymore");
     509             :         else {
     510           2 :                 mal_clients[idx].querytimeout = qto;
     511           2 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     512           2 :                 if (qry_ctx) {
     513           2 :                         qry_ctx->endtime = qry_ctx->starttime && qto ? qry_ctx->starttime + qto : 0;
     514             :                 }
     515             :         }
     516           2 :         MT_lock_unset(&mal_contextLock);
     517           2 :         return msg;
     518             : }
     519             : 
     520             : /* Set the current session timeout in seconds */
     521             : static str
     522        2480 : CLTsessionTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     523             : {
     524        2480 :         str msg = MAL_SUCCEED;
     525        2480 :         int sto = -1, idx = cntxt->idx;
     526        2480 :         (void) mb;
     527             : 
     528        2480 :         if (pci->argc == 3) {
     529           0 :                 if (cntxt->user == MAL_ADMIN) {
     530           0 :                         idx = *getArgReference_int(stk, pci, 1);
     531           0 :                         sto = *getArgReference_int(stk, pci, 2);
     532             :                 } else {
     533           0 :                         throw(MAL, "clients.setsessiontimeout",
     534             :                                   SQLSTATE(42000) "Administrator rights required");
     535             :                 }
     536             :         } else {
     537        2480 :                 sto = *getArgReference_int(stk, pci, 1);
     538             :         }
     539        2480 :         if (is_int_nil(sto))
     540           0 :                 throw(MAL, "clients.setsessiontimeout",
     541             :                           "Session timeout cannot be NULL");
     542        2480 :         if (sto < 0)
     543           1 :                 throw(MAL, "clients.setsessiontimeout",
     544             :                           "Session timeout should be >= 0");
     545        2479 :         if (idx < 0 || idx > MAL_MAXCLIENTS)
     546           0 :                 throw(MAL, "clients.setsessiontimeout", "Illegal session id %d", idx);
     547             : 
     548        2479 :         MT_lock_set(&mal_contextLock);
     549        2479 :         if (mal_clients[idx].mode == FREECLIENT)
     550           0 :                 msg = createException(MAL, "clients.setsessiontimeout",
     551             :                                                           "Session not active anymore");
     552             :         else {
     553        2479 :                 mal_clients[idx].sessiontimeout = sto > 0 ? (lng) sto *1000000 + (GDKusec() - mal_clients[idx].session) : 0;
     554        2479 :                 mal_clients[idx].logical_sessiontimeout = (lng) sto;
     555             :         }
     556        2479 :         MT_lock_unset(&mal_contextLock);
     557        2479 :         return msg;
     558             : }
     559             : 
     560             : /* Retrieve the session time out */
     561             : static str
     562           0 : CLTgetProfile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     563             : {
     564           0 :         str *opt = getArgReference_str(stk, pci, 0);
     565           0 :         int *qto = getArgReference_int(stk, pci, 1);
     566           0 :         int *sto = getArgReference_int(stk, pci, 2);
     567           0 :         int *wlim = getArgReference_int(stk, pci, 3);
     568           0 :         int *mlim = getArgReference_int(stk, pci, 4);
     569           0 :         (void) mb;
     570           0 :         if (!(*opt = GDKstrdup(cntxt->optimizer)))
     571           0 :                 throw(MAL, "clients.getProfile", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     572           0 :         *qto = (int) (cntxt->querytimeout / 1000000);
     573           0 :         *sto = (int) (cntxt->sessiontimeout / 1000000);
     574           0 :         *wlim = cntxt->workerlimit;
     575           0 :         *mlim = cntxt->memorylimit;
     576           0 :         return MAL_SUCCEED;
     577             : }
     578             : 
     579             : /* Long running queries are traced in the logger
     580             :  * with a message from the interpreter.
     581             :  * This value should be set to minutes to avoid a lengthly log */
     582             : static str
     583           0 : CLTsetPrintTimeout(void *ret, int *secs)
     584             : {
     585           0 :         (void) ret;
     586           0 :         if (is_int_nil(*secs))
     587           0 :                 setqptimeout(0);
     588             :         else
     589           0 :                 setqptimeout((lng) *secs * 60 * 1000000);
     590           0 :         return MAL_SUCCEED;
     591             : }
     592             : 
     593             : static str
     594          14 : CLTmd5sum(str *ret, str *pw)
     595             : {
     596          14 :         if (strNil(*pw)) {
     597           1 :                 *ret = GDKstrdup(str_nil);
     598             :         } else {
     599          13 :                 char *mret = mcrypt_MD5Sum(*pw, strlen(*pw));
     600             : 
     601          13 :                 if (!mret)
     602           0 :                         throw(MAL, "clients.md5sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     603          13 :                 *ret = GDKstrdup(mret);
     604          13 :                 free(mret);
     605             :         }
     606          14 :         if (*ret == NULL)
     607           0 :                 throw(MAL, "clients.md5sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     608             :         return MAL_SUCCEED;
     609             : }
     610             : 
     611             : static str
     612           1 : CLTsha1sum(str *ret, str *pw)
     613             : {
     614           1 :         if (strNil(*pw)) {
     615           0 :                 *ret = GDKstrdup(str_nil);
     616             :         } else {
     617           1 :                 char *mret = mcrypt_SHA1Sum(*pw, strlen(*pw));
     618             : 
     619           1 :                 if (!mret)
     620           0 :                         throw(MAL, "clients.sha1sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     621           1 :                 *ret = GDKstrdup(mret);
     622           1 :                 free(mret);
     623             :         }
     624           1 :         if (*ret == NULL)
     625           0 :                 throw(MAL, "clients.sha1sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     626             :         return MAL_SUCCEED;
     627             : }
     628             : 
     629             : static str
     630           1 : CLTripemd160sum(str *ret, str *pw)
     631             : {
     632           1 :         if (strNil(*pw)) {
     633           0 :                 *ret = GDKstrdup(str_nil);
     634             :         } else {
     635           1 :                 char *mret = mcrypt_RIPEMD160Sum(*pw, strlen(*pw));
     636             : 
     637           1 :                 if (!mret)
     638           0 :                         throw(MAL, "clients.ripemd160sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     639           1 :                 *ret = GDKstrdup(mret);
     640           1 :                 free(mret);
     641             :         }
     642           1 :         if (*ret == NULL)
     643           0 :                 throw(MAL, "clients.ripemd160sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     644             :         return MAL_SUCCEED;
     645             : }
     646             : 
     647             : static str
     648           4 : CLTsha2sum(str *ret, str *pw, int *bits)
     649             : {
     650           8 :         if (strNil(*pw) || is_int_nil(*bits)) {
     651           0 :                 *ret = GDKstrdup(str_nil);
     652             :         } else {
     653           4 :                 char *mret = 0;
     654           4 :                 switch (*bits) {
     655           1 :                 case 512:
     656           1 :                         mret = mcrypt_SHA512Sum(*pw, strlen(*pw));
     657           1 :                         break;
     658           1 :                 case 384:
     659           1 :                         mret = mcrypt_SHA384Sum(*pw, strlen(*pw));
     660           1 :                         break;
     661           1 :                 case 256:
     662           1 :                         mret = mcrypt_SHA256Sum(*pw, strlen(*pw));
     663           1 :                         break;
     664           1 :                 case 224:
     665           1 :                         mret = mcrypt_SHA224Sum(*pw, strlen(*pw));
     666           1 :                         break;
     667           0 :                 default:
     668           0 :                         (void) mret;
     669           0 :                         throw(ILLARG, "clients.sha2sum", "wrong number of bits "
     670             :                                   "for SHA2 sum: %d", *bits);
     671             :                 }
     672           4 :                 if (!mret)
     673           0 :                         throw(MAL, "clients.sha2sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     674           4 :                 *ret = GDKstrdup(mret);
     675           4 :                 free(mret);
     676             :         }
     677           4 :         if (*ret == NULL)
     678           0 :                 throw(MAL, "clients.sha2sum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     679             :         return MAL_SUCCEED;
     680             : }
     681             : 
     682             : static str
     683           0 : CLTbackendsum(str *ret, str *pw)
     684             : {
     685           0 :         if (strNil(*pw)) {
     686           0 :                 *ret = GDKstrdup(str_nil);
     687             :         } else {
     688           0 :                 char *mret = mcrypt_BackendSum(*pw, strlen(*pw));
     689           0 :                 if (mret == NULL)
     690           0 :                         throw(MAL, "clients.backendsum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     691           0 :                 *ret = GDKstrdup(mret);
     692           0 :                 free(mret);
     693             :         }
     694           0 :         if (*ret == NULL)
     695           0 :                 throw(MAL, "clients.backendsum", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     696             :         return MAL_SUCCEED;
     697             : }
     698             : 
     699             : static str
     700           5 : CLTgetUsername(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     701             : {
     702           5 :         str *ret = getArgReference_str(stk, pci, 0);
     703           5 :         (void) mb;
     704             : 
     705           5 :         *ret = GDKstrdup(cntxt->username);
     706           5 :         return MAL_SUCCEED;
     707             : }
     708             : 
     709             : static str
     710           0 : CLTgetPasswordHash(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     711             : {
     712           0 :         (void) cntxt;
     713           0 :         (void) mb;
     714           0 :         (void) stk;
     715           0 :         (void) pci;
     716             : 
     717           0 :         throw(MAL, "clients.getPassword",
     718             :                   SQLSTATE(0A000) PROGRAM_NYI);
     719             : }
     720             : 
     721             : static str
     722           0 : CLTcheckPermission(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     723             : {
     724           0 :         (void) cntxt;
     725           0 :         (void) mb;
     726           0 :         (void) stk;
     727           0 :         (void) pci;
     728             : 
     729           0 :         throw(MAL, "clients.checkPermission",
     730             :                   SQLSTATE(0A000) PROGRAM_NYI);
     731             : }
     732             : 
     733             : str
     734           2 : CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     735             : {
     736           2 :         str *ret = getArgReference_str(stk, pci, 0);
     737           2 :         int delay;
     738           2 :         bit force = FALSE;
     739           2 :         int leftover;
     740           2 :         char buf[1024] = { "safe to stop last connection" };
     741             : 
     742           2 :         if (pci->argc == 3)
     743           1 :                 force = *getArgReference_bit(stk, pci, 2);
     744             : 
     745           2 :         (void) mb;
     746             : 
     747           2 :         delay = *getArgReference_bte(stk, pci, 1);
     748             : 
     749           2 :         if (cntxt->user != MAL_ADMIN)
     750           0 :                 throw(MAL, "mal.shutdown",
     751             :                           SQLSTATE(42000) "Administrator rights required");
     752           2 :         if (is_int_nil(delay))
     753             :                 throw(MAL, "mal.shutdown", "Delay cannot be NULL");
     754           2 :         if (delay < 0)
     755           0 :                 throw(MAL, "mal.shutdown", "Delay cannot be negative");
     756           2 :         if (is_bit_nil(force))
     757           0 :                 throw(MAL, "mal.shutdown", "Force cannot be NULL");
     758           2 :         MCstopClients(cntxt);
     759           2 :         do {
     760           2 :                 if ((leftover = MCactiveClients() - 1))
     761           0 :                         MT_sleep_ms(1000);
     762           2 :                 delay--;
     763           2 :         } while (delay > 0 && leftover > 1);
     764           2 :         if (delay == 0 && leftover > 1)
     765           0 :                 snprintf(buf, 1024, "%d client sessions still running", leftover);
     766           2 :         *ret = GDKstrdup(buf);
     767           2 :         if (force)
     768           1 :                 GDKprepareExit();
     769           2 :         if (*ret == NULL)
     770           0 :                 throw(MAL, "mal.shutdown", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     771             :         return MAL_SUCCEED;
     772             : }
     773             : 
     774             : str
     775          25 : CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     776             : {
     777          25 :         BAT *id = NULL, *user = NULL, *login = NULL, *sessiontimeout = NULL,
     778          25 :                 *querytimeout = NULL, *idle = NULL;
     779          25 :         BAT *opt = NULL, *wlimit = NULL, *mlimit = NULL;
     780          25 :         bat *idId = getArgReference_bat(stk, pci, 0);
     781          25 :         bat *userId = getArgReference_bat(stk, pci, 1);
     782          25 :         bat *loginId = getArgReference_bat(stk, pci, 2);
     783          25 :         bat *idleId = getArgReference_bat(stk, pci, 3);
     784          25 :         bat *optId = getArgReference_bat(stk, pci, 4);
     785          25 :         bat *sessiontimeoutId = getArgReference_bat(stk, pci, 5);
     786          25 :         bat *querytimeoutId = getArgReference_bat(stk, pci, 6);
     787          25 :         bat *wlimitId = getArgReference_bat(stk, pci, 7);
     788          25 :         bat *mlimitId = getArgReference_bat(stk, pci, 8);
     789          25 :         Client c;
     790          25 :         timestamp ret;
     791          25 :         int timeout;
     792          25 :         str msg = NULL;
     793             : 
     794          25 :         (void) cntxt;
     795          25 :         (void) mb;
     796             : 
     797          25 :         id = COLnew(0, TYPE_int, 0, TRANSIENT);
     798          25 :         user = COLnew(0, TYPE_str, 0, TRANSIENT);
     799          25 :         login = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
     800          25 :         opt = COLnew(0, TYPE_str, 0, TRANSIENT);
     801          25 :         sessiontimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
     802          25 :         querytimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
     803          25 :         wlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
     804          25 :         mlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
     805          25 :         idle = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
     806             : 
     807          25 :         if (id == NULL || user == NULL || login == NULL || sessiontimeout == NULL
     808          25 :                 || idle == NULL || querytimeout == NULL || opt == NULL || wlimit == NULL
     809          25 :                 || mlimit == NULL) {
     810           0 :                 BBPreclaim(id);
     811           0 :                 BBPreclaim(user);
     812           0 :                 BBPreclaim(login);
     813           0 :                 BBPreclaim(sessiontimeout);
     814           0 :                 BBPreclaim(querytimeout);
     815           0 :                 BBPreclaim(idle);
     816             : 
     817           0 :                 BBPreclaim(opt);
     818           0 :                 BBPreclaim(wlimit);
     819           0 :                 BBPreclaim(mlimit);
     820           0 :                 throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     821             :         }
     822             : 
     823          25 :         MT_lock_set(&mal_contextLock);
     824             : 
     825        1625 :         for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
     826        1600 :                 if (c->mode == RUNCLIENT) {
     827          25 :                         const char *username = c->username;
     828          25 :                         if (!username)
     829           0 :                                 username = str_nil;
     830          25 :                         if (BUNappend(user, username, false) != GDK_SUCCEED)
     831           0 :                                 goto bailout;
     832          25 :                         ret = timestamp_fromtime(c->login);
     833          25 :                         if (is_timestamp_nil(ret)) {
     834           0 :                                 msg = createException(SQL, "sql.sessions",
     835             :                                                                           SQLSTATE(22003)
     836             :                                                                           "Failed to convert user logged time");
     837           0 :                                 goto bailout;
     838             :                         }
     839          25 :                         if (BUNappend(id, &c->idx, false) != GDK_SUCCEED)
     840           0 :                                  goto bailout;
     841          25 :                         if (BUNappend(login, &ret, false) != GDK_SUCCEED)
     842           0 :                                 goto bailout;
     843          25 :                         timeout = (int) (c->logical_sessiontimeout);
     844          25 :                         if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED)
     845           0 :                                 goto bailout;
     846          25 :                         timeout = (int) (c->querytimeout / 1000000);
     847          25 :                         if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED)
     848           0 :                                 goto bailout;
     849          25 :                         if (c->idle) {
     850           0 :                                 ret = timestamp_fromtime(c->idle);
     851           0 :                                 if (is_timestamp_nil(ret)) {
     852           0 :                                         msg = createException(SQL, "sql.sessions",
     853             :                                                                                   SQLSTATE(22003)
     854             :                                                                                   "Failed to convert user logged time");
     855           0 :                                         goto bailout;
     856             :                                 }
     857             :                         } else
     858          25 :                                 ret = timestamp_nil;
     859          25 :                         if (BUNappend(idle, &ret, false) != GDK_SUCCEED)
     860           0 :                                 goto bailout;
     861          25 :                         if (BUNappend(opt, &c->optimizer, false) != GDK_SUCCEED)
     862           0 :                                  goto bailout;
     863          25 :                         if (BUNappend(wlimit, &c->workerlimit, false) != GDK_SUCCEED)
     864           0 :                                 goto bailout;
     865          25 :                         if (BUNappend(mlimit, &c->memorylimit, false) != GDK_SUCCEED)
     866           0 :                                 goto bailout;
     867             :                 }
     868             :         }
     869          25 :         MT_lock_unset(&mal_contextLock);
     870          25 :         *idId = id->batCacheid;
     871          25 :         BBPkeepref(id);
     872          25 :         *userId = user->batCacheid;
     873          25 :         BBPkeepref(user);
     874          25 :         *loginId = login->batCacheid;
     875          25 :         BBPkeepref(login);
     876          25 :         *sessiontimeoutId = sessiontimeout->batCacheid;
     877          25 :         BBPkeepref(sessiontimeout);
     878          25 :         *querytimeoutId = querytimeout->batCacheid;
     879          25 :         BBPkeepref(querytimeout);
     880          25 :         *idleId = idle->batCacheid;
     881          25 :         BBPkeepref(idle);
     882             : 
     883          25 :         *optId = opt->batCacheid;
     884          25 :         BBPkeepref(opt);
     885          25 :         *wlimitId = wlimit->batCacheid;
     886          25 :         BBPkeepref(wlimit);
     887          25 :         *mlimitId = mlimit->batCacheid;
     888          25 :         BBPkeepref(mlimit);
     889          25 :         return MAL_SUCCEED;
     890             : 
     891           0 :   bailout:
     892           0 :         MT_lock_unset(&mal_contextLock);
     893           0 :         BBPunfix(id->batCacheid);
     894           0 :         BBPunfix(user->batCacheid);
     895           0 :         BBPunfix(login->batCacheid);
     896           0 :         BBPunfix(sessiontimeout->batCacheid);
     897           0 :         BBPunfix(querytimeout->batCacheid);
     898           0 :         BBPunfix(idle->batCacheid);
     899             : 
     900           0 :         BBPunfix(opt->batCacheid);
     901           0 :         BBPunfix(wlimit->batCacheid);
     902           0 :         BBPunfix(mlimit->batCacheid);
     903           0 :         return msg;
     904             : }
     905             : 
     906             : static str
     907           0 : CLTgetSessionID(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     908             : {
     909           0 :         (void) mb;
     910           0 :         (void) stk;
     911           0 :         (void) pci;
     912           0 :         *getArgReference_int(stk, pci, 0) = cntxt->idx;
     913           0 :         return MAL_SUCCEED;
     914             : }
     915             : 
     916             : #include "mel.h"
     917             : mel_func clients_init_funcs[] = {
     918             :  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))),
     919             :  pattern("clients", "getId", CLTgetClientId, false, "Return a number that uniquely represents the current client.", args(1,1, arg("",int))),
     920             :  pattern("clients", "getInfo", CLTInfo, false, "Pseudo bat with client attributes.", args(2,2, batarg("",str),batarg("",str))),
     921             :  pattern("clients", "getScenario", CLTgetScenario, false, "Retrieve current scenario name.", args(1,1, arg("",str))),
     922             :  pattern("clients", "setScenario", CLTsetScenario, true, "Switch to other scenario handler, return previous one.", args(1,2, arg("",str),arg("msg",str))),
     923             :  pattern("clients", "quit", CLTquit, true, "Terminate the client session.", args(1,1, arg("",void))),
     924             :  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))),
     925             :  command("clients", "getLogins", CLTLogin, false, "Pseudo bat of client id and login time.", args(2,2, batarg("user",oid),batarg("start",str))),
     926             :  pattern("clients", "stop", CLTstop, true, "Stop the query execution at the next eligble statement.", args(0,1, arg("id",int))),
     927             :  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))),
     928             :  pattern("clients", "wakeup", CLTwakeup, true, "Wakeup a client process", args(1,2, arg("",void),arg("id",int))),
     929             :  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))),
     930             :  pattern("clients", "setQryTimeoutMicro", CLTqueryTimeoutMicro, true, "", args(1,2, arg("",void),arg("n",lng))),
     931             :  pattern("clients", "setquerytimeout", CLTqueryTimeout, true, "", args(1,2, arg("",void),arg("n",int))),
     932             :  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))),
     933             :  pattern("clients", "setsessiontimeout", CLTsessionTimeout, true, "", args(1,2, arg("",void),arg("n",int))),
     934             :  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))),
     935             :  pattern("clients", "setoptimizer", CLTsetoptimizer, true, "", args(1,2, arg("",void),arg("opt",str))),
     936             :  pattern("clients", "setoptimizer", CLTsetoptimizer, true, "Set the session optimizer", args(1,3, arg("",void),arg("sid",int),arg("opt",str))),
     937             :  pattern("clients", "setworkerlimit", CLTsetworkerlimit, true, "", args(1,2, arg("",void),arg("n",int))),
     938             :  pattern("clients", "setworkerlimit", CLTsetworkerlimit, true, "Limit the number of worker threads per query", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     939             :  pattern("clients", "setmemorylimit", CLTsetmemorylimit, true, "", args(1,2, arg("",void),arg("n",int))),
     940             :  pattern("clients", "setmemorylimit", CLTsetmemorylimit, true, "Limit the memory claim in MB per query", args(1,3, arg("",void),arg("sid",int),arg("n",int))),
     941             :  pattern("clients", "stopsession", CLTstopSession, true, "Stop a particular session", args(1,2, arg("",void),arg("sid",int))),
     942             :  command("clients", "setprinttimeout", CLTsetPrintTimeout, true, "Print running query every so many seconds.", args(1,2, arg("",void),arg("n",int))),
     943             :  pattern("clients", "shutdown", CLTshutdown, true, "", args(1,2, arg("",str),arg("delay",bte))),
     944             :  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))),
     945             :  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))),
     946             :  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))),
     947             :  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))),
     948             :  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))),
     949             :  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))),
     950             :  pattern("clients", "getUsername", CLTgetUsername, false, "Return the username of the currently logged in user", args(1,1, arg("",str))),
     951             :  pattern("clients", "getPasswordHash", CLTgetPasswordHash, false, "Return the password hash of the given user", args(1,2, arg("",str),arg("user",str))),
     952             :  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))),
     953             :  pattern("clients", "current_sessionid", CLTgetSessionID, false, "return current session ID", args(1,1, arg("",int))),
     954             :  { .imp=NULL }
     955             : };
     956             : #include "mal_import.h"
     957             : #ifdef _MSC_VER
     958             : #undef read
     959             : #pragma section(".CRT$XCU",read)
     960             : #endif
     961         334 : LIB_STARTUP_FUNC(init_clients_mal)
     962         334 : { mal_module("clients", NULL, clients_init_funcs); }

Generated by: LCOV version 1.14