LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - querylog.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 169 215 78.6 %
Date: 2021-01-13 20:07:21 Functions: 13 17 76.5 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  *  Martin Kersten
      11             :  * Language Extensions
      12             :  * Iterators over scalar ranges are often needed, also at the MAL level.
      13             :  * The barrier and control primitives are sufficient to mimic them directly.
      14             :  *
      15             :  * The modules located in the kernel directory should not
      16             :  * rely on the MAL datastructures. That's why we have to deal with
      17             :  * some bat operations here and delegate the signature to the
      18             :  * proper module upon loading.
      19             :  *
      20             :  * Running a script is typically used to initialize a context.
      21             :  * Therefore we need access to the runtime context.
      22             :  * For the call variants we have
      23             :  * to determine an easy way to exchange the parameter/return values.
      24             :  */
      25             : 
      26             : #include "monetdb_config.h"
      27             : #include "querylog.h"
      28             : #include "gdk_time.h"
      29             : 
      30             : /* (c) M.L. Kersten
      31             :  * The query logger facility is hardwired to avoid interference
      32             :  * with the SQL transaction manager.
      33             :  *
      34             :  * The events being captured are stored in separate BATs.
      35             :  * They are made persistent to accumulate information over
      36             :  * multiple sessions. This means it has to be explicitly reset
      37             :  * to avoid disc overflow using querylog.reset().
      38             : create table querylog.catalog(
      39             :     id oid,
      40             :     "user" string,      -- owner of the query
      41             :     defined timestamp,  -- when entered into the cache
      42             :     query string,
      43             :     pipe string,                -- optimizer pipe-line deployed
      44             :     optimize bigint     -- time in usec
      45             : );
      46             : create table querylog.calls(
      47             :     id oid,
      48             :     "start" timestamp,  -- time the statement was started
      49             :     "stop" timestamp,   -- time the statement was completely finished
      50             :     arguments string,
      51             :     tuples lng,         -- number of tuples in the result set
      52             :     exec bigint,        -- time spent (in usec)  until the result export
      53             :     result bigint,      -- time spent (in usec)  to ship the result set
      54             :     cpuload int,        -- average cpu load percentage during execution
      55             :     iowait int         -- time waiting for IO to finish in usec
      56             : );
      57             : */
      58             : 
      59             : static bool QLOGtrace = false;
      60             : static bool QLOG_init = false;
      61             : static lng QLOGthreshold = 0;
      62             : 
      63             : static BAT *QLOG_cat_id = 0;
      64             : static BAT *QLOG_cat_user = 0;
      65             : static BAT *QLOG_cat_defined = 0;
      66             : static BAT *QLOG_cat_query = 0;
      67             : static BAT *QLOG_cat_pipe = 0;
      68             : static BAT *QLOG_cat_plan = 0;
      69             : static BAT *QLOG_cat_mal = 0;
      70             : static BAT *QLOG_cat_optimize = 0;
      71             : 
      72             : static BAT *QLOG_calls_id = 0;
      73             : static BAT *QLOG_calls_start = 0;
      74             : static BAT *QLOG_calls_stop = 0;
      75             : static BAT *QLOG_calls_arguments = 0;
      76             : static BAT *QLOG_calls_tuples = 0;
      77             : static BAT *QLOG_calls_exec = 0;
      78             : static BAT *QLOG_calls_result = 0;
      79             : static BAT *QLOG_calls_cpuload = 0;
      80             : static BAT *QLOG_calls_iowait = 0;
      81             : 
      82             : static MT_Lock QLOGlock = MT_LOCK_INITIALIZER("QLOGlock");
      83             : 
      84             : str
      85          37 : QLOGcatalog(BAT **r)
      86             : {
      87             :         int i,cnt = 0;
      88             :         str msg;
      89             : 
      90         333 :         for ( i=0;i < 8; i++)
      91         296 :                 r[i]=0;
      92          37 :         msg = initQlog();
      93          37 :         if( msg)
      94             :                 return msg;
      95          37 :         MT_lock_set(&QLOGlock);
      96          37 :         r[0] = COLcopy(QLOG_cat_id, QLOG_cat_id->ttype, false, TRANSIENT);
      97          37 :         r[1] = COLcopy(QLOG_cat_user, QLOG_cat_user->ttype,false, TRANSIENT);
      98          37 :         r[2] = COLcopy(QLOG_cat_defined, QLOG_cat_defined->ttype,false, TRANSIENT);
      99          37 :         r[3] = COLcopy(QLOG_cat_query, QLOG_cat_query->ttype,false, TRANSIENT);
     100          37 :         r[4] = COLcopy(QLOG_cat_pipe, QLOG_cat_pipe->ttype,false, TRANSIENT);
     101          37 :         r[5] = COLcopy(QLOG_cat_plan, QLOG_cat_plan->ttype,false, TRANSIENT);
     102          37 :         r[6] = COLcopy(QLOG_cat_mal, QLOG_cat_mal->ttype,false, TRANSIENT);
     103          37 :         r[7] = COLcopy(QLOG_cat_optimize, QLOG_cat_optimize->ttype,false, TRANSIENT);
     104          37 :         MT_lock_unset(&QLOGlock);
     105         333 :         for ( i = 0; i< 8; i++)
     106         296 :                 cnt += r[i] != 0;
     107          37 :         if( cnt != 8){
     108           0 :                 for ( i = 0; i< 8; i++)
     109           0 :                 if( r[i]){
     110           0 :                         BBPunfix(r[i]->batCacheid);
     111           0 :                         r[i]=0;
     112             :                 }
     113             :         }
     114          37 :         if( r[0])
     115             :                 return MAL_SUCCEED;
     116           0 :         throw(MAL,"catalog_queries", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     117             : }
     118             : 
     119             : str
     120          33 : QLOGcalls(BAT **r)
     121             : {
     122             :         int i, cnt = 0;
     123             :         str msg;
     124             : 
     125         363 :         for ( i=0;i < 10; i++)
     126         330 :                 r[i]=0;
     127          33 :         msg = initQlog();
     128          33 :         if( msg)
     129             :                 return msg;
     130          33 :         MT_lock_set(&QLOGlock);
     131          33 :         r[0] = COLcopy(QLOG_calls_id, QLOG_calls_id->ttype, false, TRANSIENT);
     132          33 :         r[1] = COLcopy(QLOG_calls_start, QLOG_calls_start->ttype,false, TRANSIENT);
     133          33 :         r[2] = COLcopy(QLOG_calls_stop, QLOG_calls_stop->ttype,false, TRANSIENT);
     134          33 :         r[3] = COLcopy(QLOG_calls_arguments, QLOG_calls_arguments->ttype,false, TRANSIENT);
     135          33 :         r[4] = COLcopy(QLOG_calls_tuples, QLOG_calls_tuples->ttype,false, TRANSIENT);
     136          33 :         r[5] = COLcopy(QLOG_calls_exec, QLOG_calls_exec->ttype,false, TRANSIENT);
     137          33 :         r[6] = COLcopy(QLOG_calls_result, QLOG_calls_result->ttype,false, TRANSIENT);
     138          33 :         r[7] = COLcopy(QLOG_calls_cpuload, QLOG_calls_cpuload->ttype,false, TRANSIENT);
     139          33 :         r[8] = COLcopy(QLOG_calls_iowait, QLOG_calls_iowait->ttype,false, TRANSIENT);
     140          33 :         MT_lock_unset(&QLOGlock);
     141         330 :         for ( i = 0; i< 9; i++)
     142         297 :                 cnt += r[i] != 0;
     143          33 :         if( cnt != 9){
     144           0 :                 for ( i = 0; i< 9; i++)
     145           0 :                 if( r[i]){
     146           0 :                         BBPunfix(r[i]->batCacheid);
     147           0 :                         r[i]=0;
     148             :                 }
     149             :         }
     150          33 :         if( r[0])
     151             :                 return MAL_SUCCEED;
     152           0 :         throw(MAL,"catalog_calls", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     153             : }
     154             : 
     155             : #define MAXCOMMITLIST 32
     156             : static bat commitlist[MAXCOMMITLIST];
     157             : static int committop=1;
     158             : 
     159             : static BAT *
     160          85 : QLOGcreate(str hnme, str tnme, int tt)
     161             : {
     162             :         BAT *b;
     163             :         char buf[128];
     164             : 
     165          85 :         snprintf(buf, 128, "querylog_%s_%s", hnme, tnme);
     166          85 :         b = BATdescriptor(BBPindex(buf));
     167          85 :         if (b)
     168             :                 return b;
     169             : 
     170          85 :         b = COLnew(0, tt, 1 << 16, PERSISTENT);
     171          85 :         if (b == NULL)
     172             :                 return NULL;
     173             : 
     174         170 :         if (BBPrename(b->batCacheid, buf) != 0 ||
     175          85 :                 BATmode(b, false) != GDK_SUCCEED) {
     176           0 :                 BBPunfix(b->batCacheid);
     177           0 :                 return NULL;
     178             :         }
     179          85 :         commitlist[committop++]= b->batCacheid;
     180             :         assert(committop < MAXCOMMITLIST);
     181          85 :         return b;
     182             : }
     183             : 
     184             : #define cleanup(X)  if (X) { (X)->batTransient = true; BBPrename((X)->batCacheid,"_"); BBPunfix((X)->batCacheid); } (X) = NULL;
     185             : 
     186             : static void
     187           0 : _QLOGcleanup(void)
     188             : {
     189           0 :         cleanup(QLOG_cat_id);
     190           0 :         cleanup(QLOG_cat_user);
     191           0 :         cleanup(QLOG_cat_defined);
     192           0 :         cleanup(QLOG_cat_query);
     193           0 :         cleanup(QLOG_cat_pipe);
     194           0 :         cleanup(QLOG_cat_plan);
     195           0 :         cleanup(QLOG_cat_mal);
     196           0 :         cleanup(QLOG_cat_optimize);
     197             : 
     198           0 :         cleanup(QLOG_calls_id);
     199           0 :         cleanup(QLOG_calls_start);
     200           0 :         cleanup(QLOG_calls_stop);
     201           0 :         cleanup(QLOG_calls_arguments);
     202           0 :         cleanup(QLOG_calls_tuples);
     203           0 :         cleanup(QLOG_calls_exec);
     204           0 :         cleanup(QLOG_calls_result);
     205           0 :         cleanup(QLOG_calls_cpuload);
     206           0 :         cleanup(QLOG_calls_iowait);
     207           0 : }
     208             : 
     209             : static str
     210           5 : _initQlog(void)
     211             : {
     212           5 :         QLOG_cat_id = QLOGcreate("cat","id",TYPE_oid);
     213           5 :         QLOG_cat_user = QLOGcreate("cat","user",TYPE_str);
     214           5 :         QLOG_cat_defined = QLOGcreate("cat","defined",TYPE_timestamp);
     215           5 :         QLOG_cat_query = QLOGcreate("cat","query",TYPE_str);
     216           5 :         QLOG_cat_pipe = QLOGcreate("cat","pipe",TYPE_str);
     217           5 :         QLOG_cat_plan = QLOGcreate("cat","size",TYPE_str);
     218           5 :         QLOG_cat_mal = QLOGcreate("cat","mal",TYPE_int);
     219           5 :         QLOG_cat_optimize = QLOGcreate("cat","optimize",TYPE_lng);
     220             : 
     221           5 :         QLOG_calls_id = QLOGcreate("calls","id",TYPE_oid);
     222           5 :         QLOG_calls_start = QLOGcreate("calls","start",TYPE_timestamp);
     223           5 :         QLOG_calls_stop = QLOGcreate("calls","stop",TYPE_timestamp);
     224           5 :         QLOG_calls_arguments = QLOGcreate("calls","arguments",TYPE_str);
     225           5 :         QLOG_calls_tuples = QLOGcreate("calls","tuples",TYPE_lng);
     226           5 :         QLOG_calls_exec = QLOGcreate("calls","exec",TYPE_lng);
     227           5 :         QLOG_calls_result = QLOGcreate("calls","result",TYPE_lng);
     228           5 :         QLOG_calls_cpuload = QLOGcreate("calls","cpuload",TYPE_int);
     229           5 :         QLOG_calls_iowait = QLOGcreate("calls","iowait",TYPE_int);
     230             : 
     231           5 :         if( QLOG_cat_id == NULL || QLOG_cat_user == NULL || QLOG_cat_defined == NULL ||
     232           5 :                 QLOG_cat_query == NULL || QLOG_cat_pipe == NULL || QLOG_cat_plan == NULL ||
     233           5 :                 QLOG_cat_mal == NULL || QLOG_cat_optimize == NULL || QLOG_calls_id == NULL ||
     234           5 :                 QLOG_calls_start == NULL || QLOG_calls_stop == NULL || QLOG_calls_arguments == NULL ||
     235           5 :                 QLOG_calls_tuples == NULL || QLOG_calls_exec == NULL || QLOG_calls_result == NULL ||
     236           5 :                 QLOG_calls_cpuload == NULL || QLOG_calls_iowait == NULL){
     237           0 :                         _QLOGcleanup();
     238           0 :                         throw(MAL,"querylog.init", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     239             :         }
     240             : 
     241           5 :         QLOG_init = true;
     242           5 :         TMsubcommit_list(commitlist, committop);
     243           5 :         return MAL_SUCCEED;
     244             : }
     245             : 
     246             : str
     247          81 : initQlog(void)
     248             : {
     249             :         str msg;
     250             : 
     251          81 :         if (QLOG_init)
     252             :                 return MAL_SUCCEED;        /* already initialized */
     253           5 :         MT_lock_set(&QLOGlock);
     254           5 :         msg = _initQlog();
     255           5 :         MT_lock_unset(&QLOGlock);
     256           5 :         return msg;
     257             : }
     258             : 
     259             : str
     260           1 : QLOGenable(void *ret)
     261             : {
     262             :         (void) ret;
     263           1 :         QLOGtrace = true;
     264           1 :         QLOGthreshold = 0;
     265           1 :         return MAL_SUCCEED;
     266             : }
     267             : 
     268             : str
     269           0 : QLOGenableThreshold(void *ret, int *threshold)
     270             : {
     271             :         (void) ret;
     272           0 :         QLOGtrace = true;
     273           0 :         QLOGthreshold = *threshold * LL_CONSTANT(1000);
     274           0 :         return MAL_SUCCEED;
     275             : }
     276             : 
     277             : str
     278           1 : QLOGdisable(void *ret)
     279             : {
     280             :         (void) ret;
     281           1 :         QLOGtrace = false;
     282           1 :         return MAL_SUCCEED;
     283             : }
     284             : 
     285             : int
     286      278963 : QLOGisset(void)
     287             : {
     288      278963 :         return QLOGtrace;
     289             : }
     290             : 
     291             : str
     292           0 : QLOGissetFcn(int *ret)
     293             : {
     294           0 :         *ret = QLOGtrace;
     295           0 :         return MAL_SUCCEED;
     296             : }
     297             : 
     298             : str
     299           1 : QLOGempty(void *ret)
     300             : {
     301             :         str msg;
     302             : 
     303             :         (void) ret;
     304           1 :         msg = initQlog();
     305           1 :         if( msg)
     306             :                 return msg;
     307           1 :         MT_lock_set(&QLOGlock);
     308             :         /* drop all querylog tables */
     309             : 
     310           1 :         BATclear(QLOG_cat_id,true);
     311           1 :         BATclear(QLOG_cat_user,true);
     312           1 :         BATclear(QLOG_cat_defined,true);
     313           1 :         BATclear(QLOG_cat_query,true);
     314           1 :         BATclear(QLOG_cat_pipe,true);
     315           1 :         BATclear(QLOG_cat_plan,true);
     316           1 :         BATclear(QLOG_cat_mal,true);
     317           1 :         BATclear(QLOG_cat_optimize,true);
     318             : 
     319           1 :         BATclear(QLOG_calls_id,true);
     320           1 :         BATclear(QLOG_calls_start,true);
     321           1 :         BATclear(QLOG_calls_stop,true);
     322           1 :         BATclear(QLOG_calls_arguments,true);
     323           1 :         BATclear(QLOG_calls_tuples,true);
     324           1 :         BATclear(QLOG_calls_exec,true);
     325           1 :         BATclear(QLOG_calls_result,true);
     326           1 :         BATclear(QLOG_calls_cpuload,true);
     327           1 :         BATclear(QLOG_calls_iowait,true);
     328             : 
     329           1 :         TMsubcommit_list(commitlist, committop);
     330           1 :         MT_lock_unset(&QLOGlock);
     331           1 :         return MAL_SUCCEED;
     332             : }
     333             : 
     334             : str
     335           5 : QLOGappend(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     336             : {
     337           5 :         oid *ret = getArgReference_oid(stk,pci,0);
     338           5 :         str *q = getArgReference_str(stk,pci,1);
     339           5 :         str *pipe = getArgReference_str(stk,pci,2);
     340           5 :         str  *usr = getArgReference_str(stk,pci,3);
     341           5 :         timestamp *tick = getArgReference_TYPE(stk,pci,4,timestamp);
     342             :         oid o;
     343           5 :         InstrPtr sig = getInstrPtr(mb,0);
     344             :         char buf[128], *nme= buf;
     345             :         str msg;
     346             : 
     347             :         (void) cntxt;
     348           5 :         msg = initQlog();
     349           5 :         if( msg)
     350             :                 return msg;
     351           5 :         snprintf(buf,128,"%s.%s", getModuleId(sig), getFunctionId(sig));
     352           5 :         MT_lock_set(&QLOGlock);
     353           5 :         o = BUNfnd(QLOG_cat_id, &mb->tag);
     354           5 :         if ( o == BUN_NONE){
     355           5 :                 *ret = mb->tag;
     356          10 :                 if (BUNappend(QLOG_cat_id,&mb->tag,false) != GDK_SUCCEED ||
     357          10 :                         BUNappend(QLOG_cat_query,*q,false) != GDK_SUCCEED ||
     358          10 :                         BUNappend(QLOG_cat_pipe,*pipe,false) != GDK_SUCCEED ||
     359          10 :                         BUNappend(QLOG_cat_plan,nme,false) != GDK_SUCCEED ||
     360          10 :                         BUNappend(QLOG_cat_mal,&mb->stop,false) != GDK_SUCCEED ||
     361          10 :                         BUNappend(QLOG_cat_optimize,&mb->optimize,false) != GDK_SUCCEED ||
     362          10 :                         BUNappend(QLOG_cat_user,*usr,false) != GDK_SUCCEED ||
     363           5 :                         BUNappend(QLOG_cat_defined,tick,false) != GDK_SUCCEED) {
     364           0 :                         MT_lock_unset(&QLOGlock);
     365           0 :                         throw(MAL, "querylog.append", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     366             :                 }
     367             :         }
     368           5 :         TMsubcommit_list(commitlist, committop);
     369           5 :         MT_lock_unset(&QLOGlock);
     370           5 :         return MAL_SUCCEED;
     371             : }
     372             : 
     373             : str
     374       98418 : QLOGdefineNaive(void *ret, str *qry, str *opt, int *nr)
     375             : {
     376             :         // Nothing else to be done.
     377             :         (void) ret;
     378             :         (void) qry;
     379             :         (void) opt;
     380             :         (void) nr;
     381       98418 :         return MAL_SUCCEED;
     382             : }
     383             : 
     384             : str
     385           0 : QLOGcontextNaive(void *ret, str *release, str *version, str *revision, str *uri)
     386             : {
     387             :         // Nothing else to be done.
     388             :         (void) ret;
     389             :         (void) release;
     390             :         (void) version;
     391             :         (void) revision;
     392             :         (void) uri;
     393           0 :         return MAL_SUCCEED;
     394             : }
     395             : 
     396             : str
     397           5 : QLOGcall(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     398             : {
     399           5 :         timestamp *tick1  = getArgReference_TYPE(stk,pci,1,timestamp);
     400           5 :         timestamp *tick2  = getArgReference_TYPE(stk,pci,2,timestamp);
     401           5 :         str *arg        = getArgReference_str(stk,pci,3);
     402           5 :         lng *tuples = getArgReference_lng(stk,pci,4);
     403           5 :         lng *xtime  = getArgReference_lng(stk,pci,5);
     404           5 :         lng *rtime  = getArgReference_lng(stk,pci,6);
     405           5 :         int *cpu        = getArgReference_int(stk,pci,7);
     406           5 :         int *iowait = getArgReference_int(stk,pci,8);
     407             :         str msg;
     408             : 
     409             :         (void) cntxt;
     410             : 
     411           5 :         msg = initQlog();
     412           5 :         if( msg)
     413             :                 return msg;
     414           5 :         if ( *xtime + *rtime < QLOGthreshold)
     415             :                 return MAL_SUCCEED;
     416           5 :         MT_lock_set(&QLOGlock);
     417          10 :         if (BUNappend(QLOG_calls_id,&mb->tag,false) != GDK_SUCCEED ||
     418          10 :                 BUNappend(QLOG_calls_start,tick1,false) != GDK_SUCCEED ||
     419          10 :                 BUNappend(QLOG_calls_stop,tick2,false) != GDK_SUCCEED ||
     420          10 :                 BUNappend(QLOG_calls_arguments,*arg,false) != GDK_SUCCEED ||
     421          10 :                 BUNappend(QLOG_calls_tuples,tuples,false) != GDK_SUCCEED ||
     422          10 :                 BUNappend(QLOG_calls_exec,xtime,false) != GDK_SUCCEED ||
     423          10 :                 BUNappend(QLOG_calls_result,rtime,false) != GDK_SUCCEED ||
     424          10 :                 BUNappend(QLOG_calls_cpuload,cpu,false) != GDK_SUCCEED ||
     425           5 :                 BUNappend(QLOG_calls_iowait,iowait,false) != GDK_SUCCEED) {
     426           0 :                 MT_lock_unset(&QLOGlock);
     427           0 :                 throw(MAL, "querylog.call", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     428             :         }
     429           5 :         TMsubcommit_list(commitlist, committop);
     430           5 :         MT_lock_unset(&QLOGlock);
     431           5 :         return MAL_SUCCEED;
     432             : }
     433             : 
     434             : #include "mel.h"
     435             : mel_func querylog_init_funcs[] = {
     436             :  command("querylog", "enable", QLOGenableThreshold, false, "Turn on the query logger", args(0,1, arg("threshold",int))),
     437             :  command("querylog", "enable", QLOGenable, false, "Turn on the query logger", noargs),
     438             :  command("querylog", "disable", QLOGdisable, false, "Turn off the query logger", noargs),
     439             :  command("querylog", "isset", QLOGissetFcn, false, "Return status of query logger", args(1,1, arg("",int))),
     440             :  command("querylog", "empty", QLOGempty, false, "Clear the query log tables", noargs),
     441             :  pattern("querylog", "append", QLOGappend, false, "Add a new query call to the query log", args(0,4, arg("q",str),arg("pipe",str),arg("usr",str),arg("tick",timestamp))),
     442             :  command("querylog", "define", QLOGdefineNaive, false, "Noop operation, just marking the query", args(0,3, arg("q",str),arg("pipe",str),arg("size",int))),
     443             :  command("querylog", "context", QLOGcontextNaive, false, "Noop operation, just marking the query", args(0,4, arg("release",str),arg("version",str),arg("revision",str),arg("uri",str))),
     444             :  pattern("querylog", "call", QLOGcall, false, "Add a new query call to the query log", args(0,8, arg("tick1",timestamp),arg("tick2",timestamp),arg("arg",str),arg("tuples",lng),arg("xtime",lng),arg("rtime",lng),arg("cpu",int),arg("iowait",int))),
     445             :  { .imp=NULL }
     446             : };
     447             : #include "mal_import.h"
     448             : #ifdef _MSC_VER
     449             : #undef read
     450             : #pragma section(".CRT$XCU",read)
     451             : #endif
     452         255 : LIB_STARTUP_FUNC(init_querylog_mal)
     453         255 : { mal_module("querylog", NULL, querylog_init_funcs); }

Generated by: LCOV version 1.14