LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - sysmon.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 205 302 67.9 %
Date: 2024-11-15 19:37:45 Functions: 6 6 100.0 %

          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             : #include "monetdb_config.h"
      14             : #include "mal.h"
      15             : #include "mal_interpreter.h"
      16             : #include "mal_authorize.h"
      17             : #include "mal_client.h"
      18             : #include "mal_runtime.h"
      19             : #include "gdk_time.h"
      20             : #include "mal_exception.h"
      21             : #include "mal_internal.h"
      22             : 
      23             : /* (c) M.L. Kersten
      24             :  * The queries currently in execution are returned to the front-end for managing expensive ones.
      25             :  */
      26             : 
      27             : static str
      28           1 : SYSMONstatistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      29             : {
      30           1 :         (void) mb;
      31             : 
      32             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
      33             :            to use this function */
      34           1 :         if (cntxt->sqlcontext == NULL)
      35           0 :                 throw(MAL, "SYSMONstatistics",
      36             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
      37             : 
      38           1 :         BAT *user, *querycount, *totalticks, *started, *finished, *maxquery,
      39             :                         *maxticks;
      40           1 :         bat *u = getArgReference_bat(stk, pci, 0);
      41           1 :         bat *c = getArgReference_bat(stk, pci, 1);
      42           1 :         bat *t = getArgReference_bat(stk, pci, 2);
      43           1 :         bat *s = getArgReference_bat(stk, pci, 3);
      44           1 :         bat *f = getArgReference_bat(stk, pci, 4);
      45           1 :         bat *m = getArgReference_bat(stk, pci, 5);
      46           1 :         bat *q = getArgReference_bat(stk, pci, 6);
      47           1 :         size_t i;
      48           1 :         timestamp tsn = timestamp_nil;
      49           1 :         str msg = MAL_SUCCEED;
      50             : 
      51           1 :         user = COLnew(0, TYPE_str, usrstatscnt, TRANSIENT);
      52           1 :         querycount = COLnew(0, TYPE_lng, usrstatscnt, TRANSIENT);
      53           1 :         totalticks = COLnew(0, TYPE_lng, usrstatscnt, TRANSIENT);
      54           1 :         started = COLnew(0, TYPE_timestamp, usrstatscnt, TRANSIENT);
      55           1 :         finished = COLnew(0, TYPE_timestamp, usrstatscnt, TRANSIENT);
      56           1 :         maxticks = COLnew(0, TYPE_lng, usrstatscnt, TRANSIENT);
      57           1 :         maxquery = COLnew(0, TYPE_str, usrstatscnt, TRANSIENT);
      58           1 :         if (user == NULL || querycount == NULL || totalticks == NULL
      59           1 :                 || started == NULL || finished == NULL || maxquery == NULL
      60           1 :                 || maxticks == NULL) {
      61           0 :                 BBPreclaim(user);
      62           0 :                 BBPreclaim(started);
      63           0 :                 BBPreclaim(querycount);
      64           0 :                 BBPreclaim(totalticks);
      65           0 :                 BBPreclaim(finished);
      66           0 :                 BBPreclaim(maxticks);
      67           0 :                 BBPreclaim(maxquery);
      68           0 :                 throw(MAL, "SYSMONstatistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      69             :         }
      70             : 
      71           1 :         MT_lock_set(&mal_delayLock);
      72             :         // FIXME: what if there are multiple users with ADMIN privilege?
      73           7 :         for (i = 0; i < usrstatscnt; i++) {
      74             :                 /* We can stop at the first empty entry */
      75           6 :                 if (USRstats[i].username == NULL)
      76             :                         break;
      77             : 
      78           5 :                 if (BUNappend(user, USRstats[i].username, false) != GDK_SUCCEED) {
      79           0 :                         msg = createException(MAL, "SYSMONstatistics",
      80             :                                                                   "Failed to append 'user'");
      81           0 :                         goto bailout;
      82             :                 }
      83           5 :                 if (BUNappend(querycount, &USRstats[i].querycount, false) != GDK_SUCCEED) {
      84           0 :                         msg = createException(MAL, "SYSMONstatistics",
      85             :                                                                   "Failed to append 'querycount'");
      86           0 :                         goto bailout;
      87             :                 }
      88           5 :                 if (BUNappend(totalticks, &USRstats[i].totalticks, false) != GDK_SUCCEED) {
      89           0 :                         msg = createException(MAL, "SYSMONstatistics",
      90             :                                                                   "Failed to append 'totalticks'");
      91           0 :                         goto bailout;
      92             :                 }
      93             :                 /* convert number of seconds into a timestamp */
      94           5 :                 if (USRstats[i].maxquery != 0) {
      95           5 :                         tsn = timestamp_fromtime(USRstats[i].started);
      96           5 :                         if (is_timestamp_nil(tsn)) {
      97           0 :                                 msg = createException(MAL, "SYSMONstatistics",
      98             :                                                                           SQLSTATE(22003)
      99             :                                                                           "failed to convert start time");
     100           0 :                                 goto bailout;
     101             :                         }
     102           5 :                         if (BUNappend(started, &tsn, false) != GDK_SUCCEED) {
     103           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     104             :                                                                           "Failed to append 'started'");
     105           0 :                                 goto bailout;
     106             :                         }
     107             : 
     108           5 :                         if (USRstats[i].finished == 0) {
     109           0 :                                 tsn = timestamp_nil;
     110             :                         } else {
     111           5 :                                 tsn = timestamp_fromtime(USRstats[i].finished);
     112           5 :                                 if (is_timestamp_nil(tsn)) {
     113           0 :                                         msg = createException(MAL, "SYSMONstatistics",
     114             :                                                                                   SQLSTATE(22003)
     115             :                                                                                   "failed to convert finish time");
     116           0 :                                         goto bailout;
     117             :                                 }
     118             :                         }
     119           5 :                         if (BUNappend(finished, &tsn, false) != GDK_SUCCEED) {
     120           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     121             :                                                                           "Failed to append 'finished'");
     122           0 :                                 goto bailout;
     123             :                         }
     124             :                 } else {
     125           0 :                         tsn = timestamp_nil;
     126           0 :                         if (BUNappend(started, &tsn, false) != GDK_SUCCEED) {
     127           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     128             :                                                                           "Failed to append 'started'");
     129           0 :                                 goto bailout;
     130             :                         }
     131           0 :                         if (BUNappend(finished, &tsn, false) != GDK_SUCCEED) {
     132           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     133             :                                                                           "Failed to append 'finished'");
     134           0 :                                 goto bailout;
     135             :                         }
     136             :                 }
     137             : 
     138           5 :                 if (BUNappend(maxticks, &USRstats[i].maxticks, false) != GDK_SUCCEED) {
     139           0 :                         msg = createException(MAL, "SYSMONstatistics",
     140             :                                                                   "Failed to append 'maxticks'");
     141           0 :                         goto bailout;
     142             :                 }
     143           5 :                 if (USRstats[i].maxquery == 0) {
     144           0 :                         if (BUNappend(maxquery, "none", false) != GDK_SUCCEED) {
     145           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     146             :                                                                           "Failed to append 'maxquery' 1");
     147           0 :                                 goto bailout;
     148             :                         }
     149             :                 } else {
     150           5 :                         if (BUNappend(maxquery, USRstats[i].maxquery, false) != GDK_SUCCEED) {
     151           0 :                                 msg = createException(MAL, "SYSMONstatistics",
     152             :                                                                           "Failed to append 'maxquery' 2");
     153           0 :                                 goto bailout;
     154             :                         }
     155             :                 }
     156             :         }
     157           1 :         MT_lock_unset(&mal_delayLock);
     158           1 :         *u = user->batCacheid;
     159           1 :         BBPkeepref(user);
     160           1 :         *c = querycount->batCacheid;
     161           1 :         BBPkeepref(querycount);
     162           1 :         *t = totalticks->batCacheid;
     163           1 :         BBPkeepref(totalticks);
     164           1 :         *s = started->batCacheid;
     165           1 :         BBPkeepref(started);
     166           1 :         *f = finished->batCacheid;
     167           1 :         BBPkeepref(finished);
     168           1 :         *m = maxticks->batCacheid;
     169           1 :         BBPkeepref(maxticks);
     170           1 :         *q = maxquery->batCacheid;
     171           1 :         BBPkeepref(maxquery);
     172           1 :         return MAL_SUCCEED;
     173             : 
     174           0 :   bailout:
     175           0 :         MT_lock_unset(&mal_delayLock);
     176           0 :         BBPunfix(user->batCacheid);
     177           0 :         BBPunfix(querycount->batCacheid);
     178           0 :         BBPunfix(totalticks->batCacheid);
     179           0 :         BBPunfix(started->batCacheid);
     180           0 :         BBPunfix(finished->batCacheid);
     181           0 :         BBPunfix(maxticks->batCacheid);
     182           0 :         BBPunfix(maxquery->batCacheid);
     183           0 :         return msg;
     184             : }
     185             : 
     186             : static str
     187          28 : SYSMONqueue(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     188             : {
     189          28 :         (void) mb;
     190             : 
     191             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
     192             :            to use this function */
     193          28 :         if (cntxt->sqlcontext == NULL)
     194           0 :                 throw(MAL, "SYSMONqueue",
     195             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
     196             : 
     197          28 :         bat *t = getArgReference_bat(stk, pci, 0),
     198          28 :                         *s = getArgReference_bat(stk, pci, 1),
     199          28 :                         *u = getArgReference_bat(stk, pci, 2),
     200          28 :                         *sd = getArgReference_bat(stk, pci, 3),
     201          28 :                         *ss = getArgReference_bat(stk, pci, 4),
     202          28 :                         *q = getArgReference_bat(stk, pci, 5),
     203          28 :                         *f = getArgReference_bat(stk, pci, 6),
     204          28 :                         *w = getArgReference_bat(stk, pci, 7),
     205          28 :                         *m = getArgReference_bat(stk, pci, 8);
     206             : 
     207          28 :         BUN sz = (BUN) qsize;
     208          28 :         BAT *tag = COLnew(0, TYPE_lng, sz, TRANSIENT),
     209          28 :                         *sessionid = COLnew(0, TYPE_int, sz, TRANSIENT),
     210          28 :                         *user = COLnew(0, TYPE_str, sz, TRANSIENT),
     211          28 :                         *started = COLnew(0, TYPE_timestamp, sz, TRANSIENT),
     212          28 :                         *status = COLnew(0, TYPE_str, sz, TRANSIENT),
     213          28 :                         *query = COLnew(0, TYPE_str, sz, TRANSIENT),
     214          28 :                         *finished = COLnew(0, TYPE_timestamp, sz, TRANSIENT),
     215          28 :                         *workers = COLnew(0, TYPE_int, sz, TRANSIENT),
     216          28 :                         *memory = COLnew(0, TYPE_int, sz, TRANSIENT);
     217             : 
     218          28 :         lng qtag;
     219          28 :         int wrk, mem;
     220          28 :         timestamp tsn;
     221          28 :         str userqueue = NULL, msg = MAL_SUCCEED;
     222             : 
     223             :         /* If pci->argc == 10, arg 9 type is a string */
     224          28 :         bool getall = false, admin = pci->argc == 10 ? true : false;
     225          28 :         if (admin) {
     226           9 :                 assert(getArgType(mb, pci, 9) == TYPE_str);
     227           9 :                 userqueue = *getArgReference_str(stk, pci, 9);
     228           9 :                 if (strcmp("ALL", userqueue) == 0)
     229           4 :                         getall = true;
     230             :         }
     231             : 
     232          28 :         if (tag == NULL || sessionid == NULL || user == NULL ||
     233          28 :                 query == NULL || started == NULL || finished == NULL ||
     234          28 :                 workers == NULL || memory == NULL) {
     235           0 :                 BBPreclaim(tag);
     236           0 :                 BBPreclaim(sessionid);
     237           0 :                 BBPreclaim(user);
     238           0 :                 BBPreclaim(started);
     239           0 :                 BBPreclaim(status);
     240           0 :                 BBPreclaim(query);
     241           0 :                 BBPreclaim(finished);
     242           0 :                 BBPreclaim(workers);
     243           0 :                 BBPreclaim(memory);
     244           0 :                 throw(MAL, "SYSMONqueue", SQLSTATE(HY001) MAL_MALLOC_FAIL);
     245             :         }
     246             : 
     247          28 :         MT_lock_set(&mal_delayLock);
     248        1036 :         for (size_t i = 0; i < qsize; i++) {
     249             :                 /* Filtering the queries according to how SYSMONqueue was called.
     250             :                    Either:
     251             :                    SYSADMIN calls sys.queue("ALL") or SYSADMIN calls sys.queue(USER)
     252             :                    or any user calls sys.queue() to retrieve its own queue. */
     253        1008 :                 if (QRYqueue[i].query &&
     254         922 :                         ((admin && getall) ||
     255          40 :                          (admin && strcmp(QRYqueue[i].username, userqueue) == 0) ||
     256             :                          ((admin == false)
     257         850 :                           && strcmp(QRYqueue[i].username, cntxt->username) == 0))) {
     258         878 :                         qtag = (lng) QRYqueue[i].tag;
     259        1756 :                         if (BUNappend(tag, &qtag, false) != GDK_SUCCEED ||
     260        1756 :                                 BUNappend(user, QRYqueue[i].username, false) != GDK_SUCCEED ||
     261         878 :                                 BUNappend(sessionid, &(QRYqueue[i].idx), false) != GDK_SUCCEED
     262         878 :                                 || BUNappend(query, QRYqueue[i].query, false) != GDK_SUCCEED
     263         878 :                                 || BUNappend(status, QRYqueue[i].status, false) != GDK_SUCCEED)
     264           0 :                                 goto bailout;
     265             :                         /* convert number of seconds into a timestamp */
     266         878 :                         tsn = timestamp_fromtime(QRYqueue[i].start);
     267         878 :                         if (is_timestamp_nil(tsn)) {
     268           0 :                                 msg = createException(MAL, "SYSMONqueue",
     269             :                                                                           SQLSTATE(22003) "Cannot convert time.");
     270           0 :                                 goto bailout;
     271             :                         }
     272         878 :                         if (BUNappend(started, &tsn, false) != GDK_SUCCEED)
     273           0 :                                 goto bailout;
     274         878 :                         if (QRYqueue[i].finished == 0)
     275          30 :                                 tsn = timestamp_nil;
     276             :                         else {
     277         848 :                                 tsn = timestamp_fromtime(QRYqueue[i].finished);
     278         848 :                                 if (is_timestamp_nil(tsn)) {
     279           0 :                                         msg = createException(MAL, "SYSMONqueue",
     280             :                                                                                   SQLSTATE(22003)
     281             :                                                                                   "Cannot convert time.");
     282           0 :                                         goto bailout;
     283             :                                 }
     284             :                         }
     285         878 :                         if (BUNappend(finished, &tsn, false) != GDK_SUCCEED)
     286           0 :                                 goto bailout;
     287         878 :                         if (QRYqueue[i].mb)
     288          30 :                                 wrk = (int) ATOMIC_GET(&QRYqueue[i].mb->workers);
     289             :                         else
     290         848 :                                 wrk = QRYqueue[i].workers;
     291         878 :                         if (QRYqueue[i].mb)
     292          30 :                                 mem = (int) (1 + QRYqueue[i].mb->memory / LL_CONSTANT(1048576));
     293             :                         else
     294         848 :                                 mem = QRYqueue[i].memory;
     295        1756 :                         if (BUNappend(workers, &wrk, false) != GDK_SUCCEED ||
     296         878 :                                 BUNappend(memory, &mem, false) != GDK_SUCCEED)
     297           0 :                                 goto bailout;
     298             :                 }
     299             :         }
     300          28 :         MT_lock_unset(&mal_delayLock);
     301          28 :         *t = tag->batCacheid;
     302          28 :         BBPkeepref(tag);
     303          28 :         *s = sessionid->batCacheid;
     304          28 :         BBPkeepref(sessionid);
     305          28 :         *u = user->batCacheid;
     306          28 :         BBPkeepref(user);
     307          28 :         *sd = started->batCacheid;
     308          28 :         BBPkeepref(started);
     309          28 :         *ss = status->batCacheid;
     310          28 :         BBPkeepref(status);
     311          28 :         *q = query->batCacheid;
     312          28 :         BBPkeepref(query);
     313          28 :         *f = finished->batCacheid;
     314          28 :         BBPkeepref(finished);
     315          28 :         *w = workers->batCacheid;
     316          28 :         BBPkeepref(workers);
     317          28 :         *m = memory->batCacheid;
     318          28 :         BBPkeepref(memory);
     319          28 :         return MAL_SUCCEED;
     320             : 
     321           0 :   bailout:
     322           0 :         MT_lock_unset(&mal_delayLock);
     323           0 :         BBPunfix(tag->batCacheid);
     324           0 :         BBPunfix(sessionid->batCacheid);
     325           0 :         BBPunfix(user->batCacheid);
     326           0 :         BBPunfix(started->batCacheid);
     327           0 :         BBPunfix(status->batCacheid);
     328           0 :         BBPunfix(query->batCacheid);
     329           0 :         BBPunfix(finished->batCacheid);
     330           0 :         BBPunfix(workers->batCacheid);
     331           0 :         BBPunfix(memory->batCacheid);
     332           0 :         return msg ? msg : createException(MAL, "SYSMONqueue",
     333             :                                                                            SQLSTATE(HY013) MAL_MALLOC_FAIL);
     334             : }
     335             : 
     336             : static str
     337           1 : SYSMONpause(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     338             : {
     339           1 :         (void) mb;
     340             : 
     341             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
     342             :            to use this function */
     343           1 :         if (cntxt->sqlcontext == NULL)
     344           0 :                 throw(MAL, "SYSMONpause",
     345             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
     346             : 
     347           1 :         oid tag = 0;
     348           1 :         size_t i = 0;
     349           1 :         bool paused = false;
     350           1 :         bool admin = pci->argc == 3 ? true : false;
     351           1 :         int owner = -1;
     352             : 
     353           1 :         assert(getArgType(mb, pci, 1) == TYPE_lng);
     354             : 
     355           1 :         if ((tag = (oid) *getArgReference_lng(stk, pci, 1)) < 1)
     356           0 :                 throw(MAL, "SYSMONpause", SQLSTATE(22003) "Tag must be positive.");
     357           1 :         if (tag == cntxt->curprg->def->tag)
     358           0 :                 throw(MAL, "SYSMONpause",
     359             :                           SQLSTATE(HY009) "SYSMONpause cannot pause itself.");
     360             : 
     361           1 :         MT_lock_set(&mal_delayLock);
     362           9 :         for (i = 0; i < qsize; i++) {
     363           8 :                 if (QRYqueue[i].tag == tag) {
     364           1 :                         if (QRYqueue[i].stk) {
     365           1 :                                 if (admin
     366           0 :                                         || (owner = strcmp(QRYqueue[i].username, cntxt->username)) == 0) {
     367           1 :                                         QRYqueue[i].stk->status = 'p';
     368           1 :                                         QRYqueue[i].status = "paused";
     369           1 :                                         paused = true;
     370             :                                 }
     371             :                                 /* tag found, but either not admin or user cannot
     372             :                                    pause that query with OID ctag */
     373             :                                 break;
     374             :                         }
     375             :                         /* tag found, but query could have already finished...
     376             :                            stack is 0 by this time.. potential problem?
     377             :                            using MAL fcn alarm.sleep exposes the above */
     378             :                         break;
     379             :                 }
     380             :         }
     381           1 :         MT_lock_unset(&mal_delayLock);
     382             : 
     383           1 :         return paused ? MAL_SUCCEED :
     384           0 :                         i == qsize ? createException(MAL, "SYSMONpause",
     385             :                                                                                  SQLSTATE(42 S12) "Tag " OIDFMT
     386             :                                                                                  " unknown.",
     387           0 :                                                                                  tag) : createException(MAL,
     388             :                                                                                                                                 "SYSMONpause",
     389             :                                                                                                                                 SQLSTATE(HY009)
     390             :                                                                                                                                 "Tag " OIDFMT
     391             :                                                                                                                                 " unknown to the user.",
     392             :                                                                                                                                 tag);
     393             : }
     394             : 
     395             : static str
     396           1 : SYSMONresume(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     397             : {
     398           1 :         (void) mb;
     399             : 
     400             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
     401             :            to use this function */
     402           1 :         if (cntxt->sqlcontext == NULL)
     403           0 :                 throw(MAL, "SYSMONresume",
     404             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
     405             : 
     406           1 :         oid tag = 0;
     407           1 :         size_t i = 0;
     408           1 :         bool paused = false;
     409           1 :         bool admin = pci->argc == 3 ? true : false;
     410           1 :         int owner = -1;
     411             : 
     412           1 :         assert(getArgType(mb, pci, 1) == TYPE_lng);
     413             : 
     414           1 :         if ((tag = (oid) *getArgReference_lng(stk, pci, 1)) < 1)
     415           0 :                 throw(MAL, "SYSMONresume", SQLSTATE(22003) "Tag must be positive.");
     416           1 :         if (tag == cntxt->curprg->def->tag)
     417           0 :                 throw(MAL, "SYSMONresume",
     418             :                           SQLSTATE(HY009) "SYSMONresume cannot pause itself.");
     419             : 
     420           1 :         MT_lock_set(&mal_delayLock);
     421           9 :         for (i = 0; i < qsize; i++) {
     422           8 :                 if (QRYqueue[i].tag == tag) {
     423           1 :                         if (QRYqueue[i].stk) {
     424           1 :                                 if (admin
     425           0 :                                         || (owner = strcmp(QRYqueue[i].username, cntxt->username)) == 0) {
     426           1 :                                         QRYqueue[i].stk->status = 0;
     427           1 :                                         QRYqueue[i].status = "running";
     428           1 :                                         paused = true;
     429             :                                 }
     430             :                                 /* tag found, but either not admin or user cannot
     431             :                                    pause that query with OID ctag */
     432             :                                 break;
     433             :                         }
     434             :                         /* tag found, but query could have already finished...
     435             :                            stack is 0 by this time.. potential problem?
     436             :                            using MAL fcn alarm.sleep exposes the above */
     437             :                         break;
     438             :                 }
     439             :         }
     440           1 :         MT_lock_unset(&mal_delayLock);
     441             : 
     442           1 :         return paused ? MAL_SUCCEED :
     443           0 :                         i == qsize ? createException(MAL, "SYSMONresume",
     444             :                                                                                  SQLSTATE(42 S12) "Tag " OIDFMT
     445             :                                                                                  " unknown.",
     446           0 :                                                                                  tag) : createException(MAL,
     447             :                                                                                                                                 "SYSMONresume",
     448             :                                                                                                                                 SQLSTATE(HY009)
     449             :                                                                                                                                 "Tag " OIDFMT
     450             :                                                                                                                                 " unknown to the user.",
     451             :                                                                                                                                 tag);
     452             : }
     453             : 
     454             : static str
     455           1 : SYSMONstop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     456             : {
     457           1 :         (void) mb;
     458             : 
     459             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
     460             :            to use this function */
     461           1 :         if (cntxt->sqlcontext == NULL)
     462           0 :                 throw(MAL, "SYSMONstop",
     463             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
     464             : 
     465           1 :         oid tag = 0;
     466           1 :         size_t i = 0;
     467           1 :         bool paused = false;
     468           1 :         bool admin = pci->argc == 3 ? true : false;
     469           1 :         int owner = -1;
     470             : 
     471           1 :         assert(getArgType(mb, pci, 1) == TYPE_lng);
     472             : 
     473           1 :         if ((tag = (oid) *getArgReference_lng(stk, pci, 1)) < 1)
     474           0 :                 throw(MAL, "SYSMONstop", SQLSTATE(22003) "Tag must be positive.");
     475           1 :         if (tag == cntxt->curprg->def->tag)
     476           0 :                 throw(MAL, "SYSMONstop",
     477             :                           SQLSTATE(HY009) "SYSMONstop cannot pause itself.");
     478             : 
     479           1 :         MT_lock_set(&mal_delayLock);
     480           6 :         for (i = 0; i < qsize; i++) {
     481           5 :                 if (QRYqueue[i].tag == tag) {
     482           1 :                         if (QRYqueue[i].stk) {
     483           1 :                                 if (admin
     484           0 :                                         || (owner = strcmp(QRYqueue[i].username, cntxt->username)) == 0) {
     485           1 :                                         QRYqueue[i].stk->status = 'q';
     486           1 :                                         QRYqueue[i].status = "stopping";
     487           1 :                                         paused = true;
     488             :                                 }
     489             :                                 /* tag found, but either not admin or user cannot
     490             :                                    pause that query with OID ctag */
     491             :                                 break;
     492             :                         }
     493             :                         /* tag found, but query could have already finished...
     494             :                            stack is 0 by this time.. potential problem?
     495             :                            using MAL fcn alarm.sleep exposes the above */
     496             :                         break;
     497             :                 }
     498             :         }
     499           1 :         MT_lock_unset(&mal_delayLock);
     500             : 
     501           1 :         return paused ? MAL_SUCCEED :
     502           0 :                         i == qsize ? createException(MAL, "SYSMONstop",
     503             :                                                                                  SQLSTATE(42 S12) "Tag " OIDFMT
     504             :                                                                                  " unknown.",
     505           0 :                                                                                  tag) : createException(MAL,
     506             :                                                                                                                                 "SYSMONstop",
     507             :                                                                                                                                 SQLSTATE(HY009)
     508             :                                                                                                                                 "Tag " OIDFMT
     509             :                                                                                                                                 " unknown to the user.",
     510             :                                                                                                                                 tag);
     511             : }
     512             : 
     513             : #include "mel.h"
     514             : mel_func sysmon_init_funcs[] = {
     515             :         pattern("sysmon", "pause", SYSMONpause, true, "Suspend query execution with OID id", args(0, 1, arg("id", lng))),
     516             :         pattern("sysmon", "pause", SYSMONpause, true, "Sysadmin call, suspend query execution with OID id belonging to user", args(0, 2, arg("id", lng), arg("user", str))),
     517             :         pattern("sysmon", "resume", SYSMONresume, true, "Resume query execution with OID id", args(0, 1, arg("id", lng))),
     518             :         pattern("sysmon", "resume", SYSMONresume, true, "Sysadmin call, resume query execution with OID id belonging to user", args(0, 2, arg("id", lng), arg("user", str))),
     519             :         pattern("sysmon", "stop", SYSMONstop, true, "Stop query execution with OID id", args(0, 1, arg("id", lng))),
     520             :         pattern("sysmon", "stop", SYSMONstop, true, "Sysadmin call, stop query execution with OID id belonging to user", args(0, 2, arg("id", lng), arg("user", str))),
     521             :         pattern("sysmon", "queue", SYSMONqueue, false, "A queue of queries that are currently being executed or recently finished", args(9, 9, batarg("tag", lng), batarg("sessionid", int), batarg("user", str), batarg("started", timestamp), batarg("status", str), batarg("query", str), batarg("finished", timestamp), batarg("workers", int), batarg("memory", int))),
     522             :         pattern("sysmon", "queue", SYSMONqueue, false, "Sysadmin call, to see either the global queue or user queue of queries that are currently being executed or recently finished", args(9, 10, batarg("tag", lng), batarg("sessionid", int), batarg("user", str), batarg("started", timestamp), batarg("status", str), batarg("query", str), batarg("finished", timestamp), batarg("workers", int), batarg("memory", int), arg("user", str))),
     523             :         pattern("sysmon", "user_statistics", SYSMONstatistics, false, "", args(7, 7, batarg("user", str), batarg("querycount", lng), batarg("totalticks", lng), batarg("started", timestamp), batarg("finished", timestamp), batarg("maxticks", lng), batarg("maxquery", str))),
     524             :         { .imp=NULL }
     525             : };
     526             : #include "mal_import.h"
     527             : #ifdef _MSC_VER
     528             : #undef read
     529             : #pragma section(".CRT$XCU",read)
     530             : #endif
     531         308 : LIB_STARTUP_FUNC(init_sysmon_mal)
     532         308 : { mal_module("sysmon", NULL, sysmon_init_funcs); }

Generated by: LCOV version 1.14