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 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | #include "monetdb_config.h" |
10 | #include "opt_querylog.h" |
11 | #include "mtime.h" |
12 | #include "querylog.h" |
13 | |
14 | str |
15 | OPTquerylogImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
16 | { |
17 | int i, limit, slimit; |
18 | InstrPtr p = 0, *old= mb->stmt, q,r; |
19 | int argc, io, user,nice,sys,idle,iowait,load, arg, start,finish, name; |
20 | int xtime=0, rtime = 0, tuples=0; |
21 | InstrPtr defineQuery = NULL; |
22 | char buf[256]; |
23 | lng usec = GDKusec(); |
24 | str msg = MAL_SUCCEED; |
25 | |
26 | |
27 | // query log needed? |
28 | if ( !QLOGisset() ) |
29 | return MAL_SUCCEED; |
30 | |
31 | (void) pci; |
32 | (void) stk; /* to fool compilers */ |
33 | (void) cntxt; |
34 | /* gather information */ |
35 | for (i = 1; i < mb->stop; i++) { |
36 | p = getInstrPtr(mb,i); |
37 | if ( getModuleId(p) && idcmp(getModuleId(p), "querylog" ) == 0 && idcmp(getFunctionId(p),"define" )==0){ |
38 | defineQuery= p; |
39 | getVarConstant(mb,getArg(p,3)).val.lval = GDKusec()-getVarConstant(mb,getArg(p,3)).val.lval ; |
40 | } |
41 | } |
42 | if ( defineQuery == NULL) |
43 | /* nothing to do */ |
44 | return MAL_SUCCEED; |
45 | |
46 | limit= mb->stop; |
47 | slimit= mb->ssize; |
48 | if ( newMalBlkStmt(mb, mb->ssize) < 0) |
49 | throw(MAL,"optimizer.querylog" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
50 | |
51 | pushInstruction(mb, old[0]); |
52 | /* run the querylog.define operation */ |
53 | defineQuery = copyInstruction(defineQuery); |
54 | if( defineQuery == NULL) |
55 | throw(MAL,"optimizer.querylog" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
56 | |
57 | defineQuery->argc--; // remove MAL instruction count |
58 | setFunctionId(defineQuery, appendRef); |
59 | getArg(defineQuery,0) = newTmpVariable(mb,TYPE_any); |
60 | defineQuery->token = ASSIGNsymbol; |
61 | setModuleId(defineQuery,querylogRef); |
62 | |
63 | /* collect the initial statistics */ |
64 | q = newStmt(mb, "clients" , "getUsername" ); |
65 | name= getArg(q,0)= newVariable(mb,"name" ,4,TYPE_str); |
66 | defineQuery = pushArgument(mb,defineQuery,name); |
67 | q = newStmt(mb, "mtime" , "current_timestamp" ); |
68 | start= getArg(q,0)= newVariable(mb,"start" ,5,TYPE_timestamp); |
69 | defineQuery = pushArgument(mb,defineQuery,start); |
70 | pushInstruction(mb, defineQuery); |
71 | |
72 | q = newStmt(mb, sqlRef, "argRecord" ); |
73 | for ( argc=1; argc < old[0]->argc; argc++) |
74 | q = pushArgument(mb, q, getArg(old[0],argc)); |
75 | |
76 | arg= getArg(q,0)= newVariable(mb,"args" ,4,TYPE_str); |
77 | |
78 | |
79 | q = newStmt(mb, "alarm" , "usec" ); |
80 | xtime = getArg(q,0)= newVariable(mb,"xtime" ,5,TYPE_lng); |
81 | user = newVariable(mb,"user" ,4,TYPE_lng); |
82 | nice = newVariable(mb,"nice" ,4,TYPE_lng); |
83 | sys = newVariable(mb,"sys" ,3,TYPE_lng); |
84 | idle = newVariable(mb,"idle" ,4,TYPE_lng); |
85 | iowait = newVariable(mb,"iowait" ,6,TYPE_lng); |
86 | q = newStmt(mb, "profiler" , "cpustats" ); |
87 | q->retc= q->argc =0; |
88 | q = pushReturn(mb,q,user); |
89 | q = pushReturn(mb,q,nice); |
90 | q = pushReturn(mb,q,sys); |
91 | q = pushReturn(mb,q,idle); |
92 | q = pushReturn(mb,q,iowait); |
93 | q = newAssignment(mb); |
94 | tuples= getArg(q,0) = newVariable(mb,"tuples" ,6,TYPE_lng); |
95 | (void) pushLng(mb,q,1); |
96 | |
97 | for (i = 1; i < limit; i++) { |
98 | p = old[i]; |
99 | |
100 | if (getModuleId(p)==sqlRef && |
101 | (idcmp(getFunctionId(p),"exportValue" )==0 || |
102 | idcmp(getFunctionId(p),"exportResult" )==0 ) ) { |
103 | |
104 | q = newStmt(mb, "alarm" , "usec" ); |
105 | r = newStmt(mb, calcRef, "-" ); |
106 | r = pushArgument(mb, r, getArg(q,0)); |
107 | r = pushArgument(mb, r, xtime); |
108 | getArg(r,0)=xtime; |
109 | |
110 | q = newStmt(mb, "alarm" , "usec" ); |
111 | rtime= getArg(q,0)= newVariable(mb,"rtime" ,5,TYPE_lng); |
112 | pushInstruction(mb,p); |
113 | continue; |
114 | } |
115 | if ( getModuleId(p) == sqlRef && idcmp(getFunctionId(p),"resultSet" )==0 && isaBatType(getVarType(mb,getArg(p,3)))){ |
116 | q = newStmt(mb, "aggr" , "count" ); |
117 | getArg(q,0) = tuples; |
118 | (void) pushArgument(mb,q, getArg(p,3)); |
119 | pushInstruction(mb,p); |
120 | continue; |
121 | } |
122 | if ( p->token== ENDsymbol || p->barrier == RETURNsymbol || p->barrier == YIELDsymbol){ |
123 | if ( rtime == 0){ |
124 | q = newStmt(mb, "alarm" , "usec" ); |
125 | r = newStmt(mb, calcRef, "-" ); |
126 | r = pushArgument(mb, r, getArg(q,0)); |
127 | r = pushArgument(mb, r, xtime); |
128 | getArg(r,0)=xtime; |
129 | q = newStmt(mb, "alarm" , "usec" ); |
130 | rtime= getArg(q,0)= newVariable(mb,"rtime" ,5,TYPE_lng); |
131 | } |
132 | q = newStmt(mb, "alarm" , "usec" ); |
133 | r = newStmt(mb, calcRef, "-" ); |
134 | r = pushArgument(mb, r, getArg(q,0)); |
135 | r = pushArgument(mb, r, rtime); |
136 | getArg(r,0)=rtime; |
137 | /* |
138 | * Post execution statistics gathering |
139 | */ |
140 | q = newStmt(mb, "mtime" , "current_timestamp" ); |
141 | finish= getArg(q,0)= newVariable(mb,"finish" ,6,TYPE_any); |
142 | |
143 | q = newStmt(mb, "profiler" , "cpuload" ); |
144 | load = newVariable(mb,"load" ,4,TYPE_int); |
145 | getArg(q,0)= load; |
146 | io = newVariable(mb,"io" ,2,TYPE_int); |
147 | q= pushReturn(mb,q,io); |
148 | q = pushArgument(mb,q,user); |
149 | q = pushArgument(mb,q,nice); |
150 | q = pushArgument(mb,q,sys); |
151 | q = pushArgument(mb,q,idle); |
152 | q = pushArgument(mb,q,iowait); |
153 | |
154 | q = newStmt(mb, querylogRef, "call" ); |
155 | q = pushArgument(mb, q, start); |
156 | q = pushArgument(mb, q, finish); |
157 | q = pushArgument(mb, q, arg); |
158 | q = pushArgument(mb, q, tuples); |
159 | q = pushArgument(mb, q, xtime); |
160 | q = pushArgument(mb, q, rtime); |
161 | q = pushArgument(mb, q, load); |
162 | q = pushArgument(mb, q, io); |
163 | pushInstruction(mb,p); |
164 | continue; |
165 | } |
166 | |
167 | pushInstruction(mb,p); |
168 | if (p->barrier == YIELDsymbol){ |
169 | /* the factory yield may return */ |
170 | q = newStmt(mb, "mtime" , "current_timestamp" ); |
171 | start= getArg(q,0)= newVariable(mb,"start" ,5,TYPE_any); |
172 | q = newStmt(mb, sqlRef, "argRecord" ); |
173 | for ( argc=1; argc < old[0]->argc; argc++) |
174 | q = pushArgument(mb, q, getArg(old[0],argc)); |
175 | arg= getArg(q,0)= newVariable(mb,"args" ,4,TYPE_str); |
176 | q = newAssignment(mb); |
177 | q = pushLng(mb,q,0); |
178 | q = newAssignment(mb); |
179 | q = pushLng(mb,q,0); |
180 | tuples= getArg(q,0)= newVariable(mb,"tuples" ,6,TYPE_lng); |
181 | newFcnCall(mb,"profiler" ,"setMemoryFlag" ); |
182 | q->argc--; |
183 | pushLng(mb,q,1); |
184 | q = newStmt(mb, "alarm" , "usec" ); |
185 | xtime = getArg(q,0)= newVariable(mb,"xtime" ,5,TYPE_lng); |
186 | } |
187 | } |
188 | |
189 | for( ; i<slimit; i++) |
190 | if(old[i]) |
191 | freeInstruction(old[i]); |
192 | GDKfree(old); |
193 | /* Defense line against incorrect plans */ |
194 | if( 1){ |
195 | chkTypes(cntxt->usermodule, mb, FALSE); |
196 | chkFlow(mb); |
197 | chkDeclarations(mb); |
198 | } |
199 | /* keep all actions taken as a post block comment */ |
200 | usec = GDKusec()- usec; |
201 | snprintf(buf,256,"%-20s actions= 1 time=" LLFMT " usec" ,"querylog" , usec); |
202 | newComment(mb,buf); |
203 | addtoMalBlkHistory(mb); |
204 | if( OPTdebug & OPTquerylog){ |
205 | fprintf(stderr, "#QUERYLOG optimizer exit\n" ); |
206 | fprintFunction(stderr, mb, 0, LIST_MAL_ALL); |
207 | } |
208 | return msg; |
209 | } |
210 | |