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-10-04 20:04:04 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          36 : SYSMONqueue(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     188             : {
     189          36 :         (void) mb;
     190             : 
     191             :         /* Temporary hack not allowing MAL clients (mclient -lmal)
     192             :            to use this function */
     193          36 :         if (cntxt->sqlcontext == NULL)
     194           0 :                 throw(MAL, "SYSMONqueue",
     195             :                           SQLSTATE(42000) "Calling from a mclient -lmal.");
     196             : 
     197          36 :         bat *t = getArgReference_bat(stk, pci, 0),
     198          36 :                         *s = getArgReference_bat(stk, pci, 1),
     199          36 :                         *u = getArgReference_bat(stk, pci, 2),
     200          36 :                         *sd = getArgReference_bat(stk, pci, 3),
     201          36 :                         *ss = getArgReference_bat(stk, pci, 4),
     202          36 :                         *q = getArgReference_bat(stk, pci, 5),
     203          36 :                         *f = getArgReference_bat(stk, pci, 6),
     204          36 :                         *w = getArgReference_bat(stk, pci, 7),
     205          36 :                         *m = getArgReference_bat(stk, pci, 8);
     206             : 
     207          36 :         BUN sz = (BUN) qsize;
     208          36 :         BAT *tag = COLnew(0, TYPE_lng, sz, TRANSIENT),
     209          36 :                         *sessionid = COLnew(0, TYPE_int, sz, TRANSIENT),
     210          36 :                         *user = COLnew(0, TYPE_str, sz, TRANSIENT),
     211          36 :                         *started = COLnew(0, TYPE_timestamp, sz, TRANSIENT),
     212          36 :                         *status = COLnew(0, TYPE_str, sz, TRANSIENT),
     213          36 :                         *query = COLnew(0, TYPE_str, sz, TRANSIENT),
     214          36 :                         *finished = COLnew(0, TYPE_timestamp, sz, TRANSIENT),
     215          36 :                         *workers = COLnew(0, TYPE_int, sz, TRANSIENT),
     216          36 :                         *memory = COLnew(0, TYPE_int, sz, TRANSIENT);
     217             : 
     218          36 :         lng qtag;
     219          36 :         int wrk, mem;
     220          36 :         timestamp tsn;
     221          36 :         str userqueue = NULL, msg = MAL_SUCCEED;
     222             : 
     223             :         /* If pci->argc == 10, arg 9 type is a string */
     224          36 :         bool getall = false, admin = pci->argc == 10 ? true : false;
     225          36 :         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          36 :         if (tag == NULL || sessionid == NULL || user == NULL ||
     233          36 :                 query == NULL || started == NULL || finished == NULL ||
     234          36 :                 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          36 :         MT_lock_set(&mal_delayLock);
     248        1556 :         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        1520 :                 if (QRYqueue[i].query &&
     254        1434 :                         ((admin && getall) ||
     255          40 :                          (admin && strcmp(QRYqueue[i].username, userqueue) == 0) ||
     256             :                          ((admin == false)
     257        1362 :                           && strcmp(QRYqueue[i].username, cntxt->username) == 0))) {
     258        1390 :                         qtag = (lng) QRYqueue[i].tag;
     259        2780 :                         if (BUNappend(tag, &qtag, false) != GDK_SUCCEED ||
     260        2780 :                                 BUNappend(user, QRYqueue[i].username, false) != GDK_SUCCEED ||
     261        1390 :                                 BUNappend(sessionid, &(QRYqueue[i].idx), false) != GDK_SUCCEED
     262        1390 :                                 || BUNappend(query, QRYqueue[i].query, false) != GDK_SUCCEED
     263        1390 :                                 || BUNappend(status, QRYqueue[i].status, false) != GDK_SUCCEED)
     264           0 :                                 goto bailout;
     265             :                         /* convert number of seconds into a timestamp */
     266        1390 :                         tsn = timestamp_fromtime(QRYqueue[i].start);
     267        1390 :                         if (is_timestamp_nil(tsn)) {
     268           0 :                                 msg = createException(MAL, "SYSMONqueue",
     269             :                                                                           SQLSTATE(22003) "Cannot convert time.");
     270           0 :                                 goto bailout;
     271             :                         }
     272        1390 :                         if (BUNappend(started, &tsn, false) != GDK_SUCCEED)
     273           0 :                                 goto bailout;
     274        1390 :                         if (QRYqueue[i].finished == 0)
     275          38 :                                 tsn = timestamp_nil;
     276             :                         else {
     277        1352 :                                 tsn = timestamp_fromtime(QRYqueue[i].finished);
     278        1352 :                                 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        1390 :                         if (BUNappend(finished, &tsn, false) != GDK_SUCCEED)
     286           0 :                                 goto bailout;
     287        1390 :                         if (QRYqueue[i].mb)
     288          38 :                                 wrk = (int) ATOMIC_GET(&QRYqueue[i].mb->workers);
     289             :                         else
     290        1352 :                                 wrk = QRYqueue[i].workers;
     291        1390 :                         if (QRYqueue[i].mb)
     292          38 :                                 mem = (int) (1 + QRYqueue[i].mb->memory / LL_CONSTANT(1048576));
     293             :                         else
     294        1352 :                                 mem = QRYqueue[i].memory;
     295        2780 :                         if (BUNappend(workers, &wrk, false) != GDK_SUCCEED ||
     296        1390 :                                 BUNappend(memory, &mem, false) != GDK_SUCCEED)
     297           0 :                                 goto bailout;
     298             :                 }
     299             :         }
     300          36 :         MT_lock_unset(&mal_delayLock);
     301          36 :         *t = tag->batCacheid;
     302          36 :         BBPkeepref(tag);
     303          36 :         *s = sessionid->batCacheid;
     304          36 :         BBPkeepref(sessionid);
     305          36 :         *u = user->batCacheid;
     306          36 :         BBPkeepref(user);
     307          36 :         *sd = started->batCacheid;
     308          36 :         BBPkeepref(started);
     309          36 :         *ss = status->batCacheid;
     310          36 :         BBPkeepref(status);
     311          36 :         *q = query->batCacheid;
     312          36 :         BBPkeepref(query);
     313          36 :         *f = finished->batCacheid;
     314          36 :         BBPkeepref(finished);
     315          36 :         *w = workers->batCacheid;
     316          36 :         BBPkeepref(workers);
     317          36 :         *m = memory->batCacheid;
     318          36 :         BBPkeepref(memory);
     319          36 :         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         323 : LIB_STARTUP_FUNC(init_sysmon_mal)
     532         323 : { mal_module("sysmon", NULL, sysmon_init_funcs); }

Generated by: LCOV version 1.14