1 /*
2 Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <ndb_global.h>
26 #include <AttributeHeader.hpp>
27 #include <NdbSqlUtil.hpp>
28 #include <NdbIndexStat.hpp>
29 #include <NdbTransaction.hpp>
30 #include "NdbDictionaryImpl.hpp"
31 #include <NdbInterpretedCode.hpp>
32 #include <NdbRecord.hpp>
33 #include "NdbIndexStatImpl.hpp"
34
NdbIndexStat()35 NdbIndexStat::NdbIndexStat() :
36 m_impl(*new NdbIndexStatImpl(*this))
37 {
38 }
39
NdbIndexStat(NdbIndexStatImpl & impl)40 NdbIndexStat::NdbIndexStat(NdbIndexStatImpl& impl) :
41 m_impl(impl)
42 {
43 }
44
~NdbIndexStat()45 NdbIndexStat::~NdbIndexStat()
46 {
47 NdbIndexStatImpl* impl = &m_impl;
48 if (this != impl)
49 delete impl;
50 }
51
52 /**
53 * addKeyPartInfo
54 * This method is used to build a standard representation of a
55 * lower or upper index bound in a buffer, which can then
56 * be used to identify a range.
57 * The buffer format is :
58 * 1 word of NdbIndexScanOperation::BoundType
59 * 1 word of ATTRINFO header containing the index attrid
60 * and the size in words of the data.
61 * 0..N words of data.
62 * The data itself is formatted as usual (e.g. 1/2 length
63 * bytes for VAR* types)
64 * For NULLs, length==0
65 */
66
67 int
addKeyPartInfo(const NdbRecord * record,const char * keyRecordData,Uint32 keyPartNum,const NdbIndexScanOperation::BoundType boundType,Uint32 * keyStatData,Uint32 & keyLength)68 NdbIndexStat::addKeyPartInfo(const NdbRecord* record,
69 const char* keyRecordData,
70 Uint32 keyPartNum,
71 const NdbIndexScanOperation::BoundType boundType,
72 Uint32* keyStatData,
73 Uint32& keyLength)
74 {
75 char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
76
77 Uint32 key_index= record->key_indexes[ keyPartNum ];
78 const NdbRecord::Attr *column= &record->columns[ key_index ];
79
80 bool is_null= column->is_null(keyRecordData);
81 Uint32 len= 0;
82 const void *aValue= keyRecordData + column->offset;
83
84 if (!is_null)
85 {
86 bool len_ok;
87 /* Support for special mysqld varchar format in keys. */
88 if (column->flags & NdbRecord::IsMysqldShrinkVarchar)
89 {
90 len_ok= column->shrink_varchar(keyRecordData,
91 len,
92 buf);
93 aValue= buf;
94 }
95 else
96 {
97 len_ok= column->get_var_length(keyRecordData, len);
98 }
99 if (!len_ok) {
100 m_impl.setError(4209, __LINE__);
101 return -1;
102 }
103 }
104
105 /* Insert attribute header. */
106 Uint32 tIndexAttrId= column->index_attrId;
107 Uint32 sizeInWords= (len + 3) / 4;
108 AttributeHeader ah(tIndexAttrId, sizeInWords << 2);
109 const Uint32 ahValue= ah.m_value;
110
111 if (keyLength + (2 + len) > NdbIndexStatImpl::BoundBufWords )
112 {
113 /* Something wrong, key data would be too big */
114 /* Key size is limited to 4092 bytes */
115 m_impl.setError(4207, __LINE__);
116 return -1;
117 }
118
119 /* Fill in key data */
120 keyStatData[ keyLength++ ]= boundType;
121 keyStatData[ keyLength++ ]= ahValue;
122 /* Zero last word prior to byte copy, in case we're not aligned */
123 keyStatData[ keyLength + sizeInWords - 1] = 0;
124 memcpy(&keyStatData[ keyLength ], aValue, len);
125
126 keyLength+= sizeInWords;
127
128 return 0;
129 }
130
131 int
records_in_range(const NdbDictionary::Index * index,NdbTransaction * trans,const NdbRecord * key_record,const NdbRecord * result_record,const NdbIndexScanOperation::IndexBound * ib,Uint64 table_rows,Uint64 * count,int flags)132 NdbIndexStat::records_in_range(const NdbDictionary::Index* index,
133 NdbTransaction* trans,
134 const NdbRecord* key_record,
135 const NdbRecord* result_record,
136 const NdbIndexScanOperation::IndexBound* ib,
137 Uint64 table_rows,
138 Uint64* count,
139 int flags)
140 {
141 DBUG_ENTER("NdbIndexStat::records_in_range");
142 Uint64 rows;
143 Uint32 key1[NdbIndexStatImpl::BoundBufWords], keylen1;
144 Uint32 key2[NdbIndexStatImpl::BoundBufWords], keylen2;
145
146 if (true)
147 {
148 // get start and end key from NdbIndexBound, using NdbRecord to
149 // get values into a standard format.
150 Uint32 maxBoundParts= (ib->low_key_count > ib->high_key_count) ?
151 ib->low_key_count : ib->high_key_count;
152
153 keylen1= keylen2= 0;
154
155 /* Fill in keyX buffers */
156 for (Uint32 keyPartNum=0; keyPartNum < maxBoundParts; keyPartNum++)
157 {
158 if (ib->low_key_count > keyPartNum)
159 {
160 /* Set bound to LT only if it's not inclusive
161 * and this is the last key
162 */
163 NdbIndexScanOperation::BoundType boundType=
164 NdbIndexScanOperation::BoundLE;
165 if ((! ib->low_inclusive) &&
166 (keyPartNum == (ib->low_key_count -1 )))
167 boundType= NdbIndexScanOperation::BoundLT;
168
169 if (addKeyPartInfo(key_record,
170 ib->low_key,
171 keyPartNum,
172 boundType,
173 key1,
174 keylen1) != 0)
175 DBUG_RETURN(-1);
176 }
177 if (ib->high_key_count > keyPartNum)
178 {
179 /* Set bound to GT only if it's not inclusive
180 * and this is the last key
181 */
182 NdbIndexScanOperation::BoundType boundType=
183 NdbIndexScanOperation::BoundGE;
184 if ((! ib->high_inclusive) &&
185 (keyPartNum == (ib->high_key_count -1)))
186 boundType= NdbIndexScanOperation::BoundGT;
187
188 if (addKeyPartInfo(key_record,
189 ib->high_key,
190 keyPartNum,
191 boundType,
192 key2,
193 keylen2) != 0)
194 DBUG_RETURN(-1);
195 }
196 }
197 }
198
199 if (true)
200 {
201 Uint32 out[4] = { 0, 0, 0, 0 }; // rows, in, before, after
202 float tot[4] = { 0, 0, 0, 0 }; // totals of above
203 int cnt, ret;
204 bool forceSend = true;
205 const Uint32 codeWords= 1;
206 Uint32 codeSpace[ codeWords ];
207 NdbInterpretedCode code(NULL, // No table
208 &codeSpace[0],
209 codeWords);
210 if ((code.interpret_exit_last_row() != 0) ||
211 (code.finalise() != 0))
212 {
213 m_impl.setError(code.getNdbError().code, __LINE__);
214 DBUG_PRINT("error", ("code: %d", code.getNdbError().code));
215 DBUG_RETURN(-1);
216 }
217
218 NdbIndexScanOperation* op= NULL;
219 NdbScanOperation::ScanOptions options;
220 NdbOperation::GetValueSpec extraGet;
221
222 options.optionsPresent=
223 NdbScanOperation::ScanOptions::SO_GETVALUE |
224 NdbScanOperation::ScanOptions::SO_INTERPRETED;
225
226 /* Read RECORDS_IN_RANGE pseudo column */
227 extraGet.column= NdbDictionary::Column::RECORDS_IN_RANGE;
228 extraGet.appStorage= (void*) out;
229 extraGet.recAttr= NULL;
230
231 options.extraGetValues= &extraGet;
232 options.numExtraGetValues= 1;
233
234 /* Add interpreted code to return on 1st row */
235 options.interpretedCode= &code;
236
237 const Uint32 keyBitmaskWords= (NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY + 31) >> 5;
238 Uint32 emptyMask[keyBitmaskWords];
239 memset(&emptyMask[0], 0, keyBitmaskWords << 2);
240
241 if (NULL ==
242 (op= trans->scanIndex(key_record,
243 result_record,
244 NdbOperation::LM_CommittedRead,
245 (const unsigned char*) &emptyMask[0],
246 ib,
247 &options,
248 sizeof(NdbScanOperation::ScanOptions))))
249 {
250 m_impl.setError(trans->getNdbError().code, __LINE__);
251 DBUG_PRINT("error", ("scanIndex : %d", trans->getNdbError().code));
252 DBUG_RETURN(-1);
253 }
254
255 if (trans->execute(NdbTransaction::NoCommit,
256 NdbOperation::AbortOnError, forceSend) == -1) {
257 m_impl.setError(trans->getNdbError().code, __LINE__);
258 DBUG_PRINT("error", ("trans:%d op:%d", trans->getNdbError().code,
259 op->getNdbError().code));
260 DBUG_RETURN(-1);
261 }
262 cnt = 0;
263 const char* dummy_out_ptr= NULL;
264 while ((ret = op->nextResult(&dummy_out_ptr,
265 true, forceSend)) == 0) {
266 DBUG_PRINT("info", ("frag rows=%u in=%u before=%u after=%u [error=%d]",
267 out[0], out[1], out[2], out[3],
268 (int)(out[1] + out[2] + out[3]) - (int)out[0]));
269 unsigned i;
270 for (i = 0; i < 4; i++)
271 tot[i] += (float)out[i];
272 cnt++;
273 }
274 if (ret == -1) {
275 m_impl.setError(op->getNdbError().code, __LINE__);
276 DBUG_PRINT("error nextResult ", ("trans:%d op:%d", trans->getNdbError().code,
277 op->getNdbError().code));
278 DBUG_RETURN(-1);
279 }
280 op->close(forceSend);
281 rows = (Uint64)tot[1];
282 }
283
284 *count = rows;
285 DBUG_PRINT("value", ("rows=%u/%u flags=%x",
286 (unsigned)(rows>>32), (unsigned)(rows), flags));
287 DBUG_RETURN(0);
288 }
289
290 // stored stats
291
292 int
create_systables(Ndb * ndb)293 NdbIndexStat::create_systables(Ndb* ndb)
294 {
295 DBUG_ENTER("NdbIndexStat::create_systables");
296 if (m_impl.create_systables(ndb) == -1)
297 DBUG_RETURN(-1);
298 DBUG_RETURN(0);
299 }
300
301 int
drop_systables(Ndb * ndb)302 NdbIndexStat::drop_systables(Ndb* ndb)
303 {
304 DBUG_ENTER("NdbIndexStat::drop_systables");
305 if (m_impl.drop_systables(ndb) == -1)
306 DBUG_RETURN(-1);
307 DBUG_RETURN(0);
308 }
309
310 int
check_systables(Ndb * ndb)311 NdbIndexStat::check_systables(Ndb* ndb)
312 {
313 DBUG_ENTER("NdbIndexStat::check_systables");
314 if (m_impl.check_systables(ndb) == -1)
315 DBUG_RETURN(-1);
316 DBUG_RETURN(0);
317 }
318
319 int
set_index(const NdbDictionary::Index & index,const NdbDictionary::Table & table)320 NdbIndexStat::set_index(const NdbDictionary::Index& index,
321 const NdbDictionary::Table& table)
322 {
323 DBUG_ENTER("NdbIndexStat::set_index");
324 if (m_impl.set_index(index, table) == -1)
325 DBUG_RETURN(-1);
326 m_impl.m_facadeHead.m_indexId = index.getObjectId();
327 m_impl.m_facadeHead.m_indexVersion = index.getObjectVersion();
328 m_impl.m_facadeHead.m_tableId = table.getObjectId();
329 DBUG_RETURN(0);
330 }
331
332 void
reset_index()333 NdbIndexStat::reset_index()
334 {
335 DBUG_ENTER("NdbIndexStat::reset_index");
336 m_impl.reset_index();
337 DBUG_VOID_RETURN;
338 }
339
340 int
update_stat(Ndb * ndb)341 NdbIndexStat::update_stat(Ndb* ndb)
342 {
343 DBUG_ENTER("NdbIndexStat::update_stat");
344 if (m_impl.update_stat(ndb, m_impl.m_facadeHead) == -1)
345 DBUG_RETURN(-1);
346 DBUG_RETURN(0);
347 }
348
349 int
delete_stat(Ndb * ndb)350 NdbIndexStat::delete_stat(Ndb* ndb)
351 {
352 DBUG_ENTER("NdbIndexStat::delete_stat");
353 if (m_impl.delete_stat(ndb, m_impl.m_facadeHead) == -1)
354 DBUG_RETURN(-1);
355 DBUG_RETURN(0);
356 }
357
358 // cache
359
360 void
move_cache()361 NdbIndexStat::move_cache()
362 {
363 DBUG_ENTER("NdbIndexStat::move_cache");
364 m_impl.move_cache();
365 DBUG_VOID_RETURN;
366 }
367
368 void
clean_cache()369 NdbIndexStat::clean_cache()
370 {
371 DBUG_ENTER("NdbIndexStat::clean_cache");
372 m_impl.clean_cache();
373 DBUG_VOID_RETURN;
374 }
375
376 void
get_cache_info(CacheInfo & info,CacheType type) const377 NdbIndexStat::get_cache_info(CacheInfo& info, CacheType type) const
378 {
379 const NdbIndexStatImpl::Cache* c = 0;
380 switch (type) {
381 case CacheBuild:
382 c = m_impl.m_cacheBuild;
383 break;
384 case CacheQuery:
385 c = m_impl.m_cacheQuery;
386 break;
387 case CacheClean:
388 c = m_impl.m_cacheClean;
389 break;
390 }
391 info.m_count = 0;
392 info.m_valid = 0;
393 info.m_sampleCount = 0;
394 info.m_totalBytes = 0;
395 info.m_save_time = 0;
396 info.m_sort_time = 0;
397 while (c != 0)
398 {
399 info.m_count += 1;
400 info.m_valid += c->m_valid;
401 info.m_sampleCount += c->m_sampleCount;
402 info.m_totalBytes += c->m_keyBytes + c->m_valueBytes + c->m_addrBytes;
403 info.m_save_time += c->m_save_time;
404 info.m_sort_time += c->m_sort_time;
405 c = c->m_nextClean;
406 }
407 // build and query cache have at most one instance
408 require(type == CacheClean || info.m_count <= 1);
409 }
410
411 // read
412
413 void
get_head(Head & head) const414 NdbIndexStat::get_head(Head& head) const
415 {
416 head = m_impl.m_facadeHead;
417 }
418
419 int
read_head(Ndb * ndb)420 NdbIndexStat::read_head(Ndb* ndb)
421 {
422 DBUG_ENTER("NdbIndexStat::read_head");
423 if (m_impl.read_head(ndb, m_impl.m_facadeHead) == -1)
424 DBUG_RETURN(-1);
425 DBUG_RETURN(0);
426 }
427
428 int
read_stat(Ndb * ndb)429 NdbIndexStat::read_stat(Ndb* ndb)
430 {
431 DBUG_ENTER("NdbIndexStat::read_stat");
432 if (m_impl.read_stat(ndb, m_impl.m_facadeHead) == -1)
433 DBUG_RETURN(-1);
434 DBUG_RETURN(0);
435 }
436
437 // bound
438
Bound(const NdbIndexStat * is,void * buffer)439 NdbIndexStat::Bound::Bound(const NdbIndexStat* is, void* buffer)
440 {
441 DBUG_ENTER("NdbIndexStat::Bound::Bound");
442 require(is != 0 && is->m_impl.m_indexSet);
443 require(buffer != 0);
444 Uint8* buf = (Uint8*)buffer;
445 // bound impl
446 Uint8* buf1 = buf;
447 UintPtr ubuf1 = (UintPtr)buf1;
448 if (ubuf1 % 8 != 0)
449 buf1 += (8 - ubuf1 % 8);
450 new (buf1) NdbIndexStatImpl::Bound(is->m_impl.m_keySpec);
451 m_impl = (void*)buf1;
452 NdbIndexStatImpl::Bound& bound = *(NdbIndexStatImpl::Bound*)m_impl;
453 // bound data
454 Uint8* buf2 = buf1 + sizeof(NdbIndexStatImpl::Bound);
455 uint used = (uint)(buf2 - buf);
456 uint bytes = BoundBufferBytes - used;
457 bound.m_data.set_buf(buf2, bytes);
458 DBUG_VOID_RETURN;
459 }
460
461 int
add_bound(Bound & bound_f,const void * value)462 NdbIndexStat::add_bound(Bound& bound_f, const void* value)
463 {
464 DBUG_ENTER("NdbIndexStat::add_bound");
465 NdbIndexStatImpl::Bound& bound =
466 *(NdbIndexStatImpl::Bound*)bound_f.m_impl;
467 Uint32 len_out;
468 if (value == 0)
469 {
470 m_impl.setError(UsageError, __LINE__);
471 DBUG_RETURN(-1);
472 }
473 if (bound.m_data.add(value, &len_out) == -1)
474 {
475 m_impl.setError(UsageError, __LINE__);
476 DBUG_RETURN(-1);
477 }
478 DBUG_RETURN(0);
479 }
480
481 int
add_bound_null(Bound & bound_f)482 NdbIndexStat::add_bound_null(Bound& bound_f)
483 {
484 DBUG_ENTER("NdbIndexStat::add_bound_null");
485 NdbIndexStatImpl::Bound& bound =
486 *(NdbIndexStatImpl::Bound*)bound_f.m_impl;
487 Uint32 len_out;
488 if (bound.m_data.add_null(&len_out) == -1)
489 {
490 m_impl.setError(UsageError, __LINE__);
491 DBUG_RETURN(-1);
492 }
493 DBUG_RETURN(0);
494 }
495
496 void
set_bound_strict(Bound & bound_f,int strict)497 NdbIndexStat::set_bound_strict(Bound& bound_f, int strict)
498 {
499 DBUG_ENTER("NdbIndexStat::set_bound_strict");
500 NdbIndexStatImpl::Bound& bound =
501 *(NdbIndexStatImpl::Bound*)bound_f.m_impl;
502 bound.m_strict = strict;
503 DBUG_VOID_RETURN;
504 }
505
506 void
reset_bound(Bound & bound_f)507 NdbIndexStat::reset_bound(Bound& bound_f)
508 {
509 DBUG_ENTER("NdbIndexStat::reset_bound");
510 NdbIndexStatImpl::Bound& bound =
511 *(NdbIndexStatImpl::Bound*)bound_f.m_impl;
512 bound.m_bound.reset();
513 bound.m_type = -1;
514 bound.m_strict = -1;
515 DBUG_VOID_RETURN;
516 }
517
518 // range
519
Range(Bound & bound1,Bound & bound2)520 NdbIndexStat::Range::Range(Bound& bound1, Bound& bound2) :
521 m_bound1(bound1),
522 m_bound2(bound2)
523 {
524 DBUG_ENTER("NdbIndexStat::Range::Range");
525 DBUG_VOID_RETURN;
526 }
527
528 int
finalize_range(Range & range_f)529 NdbIndexStat::finalize_range(Range& range_f)
530 {
531 DBUG_ENTER("NdbIndexStat::finalize_range");
532 Bound& bound1_f = range_f.m_bound1;
533 Bound& bound2_f = range_f.m_bound2;
534 NdbIndexStatImpl::Bound& bound1 =
535 *(NdbIndexStatImpl::Bound*)bound1_f.m_impl;
536 NdbIndexStatImpl::Bound& bound2 =
537 *(NdbIndexStatImpl::Bound*)bound2_f.m_impl;
538 NdbIndexStatImpl::Range range(bound1, bound2);
539 if (m_impl.finalize_range(range) == -1)
540 DBUG_RETURN(-1);
541 DBUG_RETURN(0);
542 }
543
544 void
reset_range(Range & range)545 NdbIndexStat::reset_range(Range& range)
546 {
547 DBUG_ENTER("NdbIndexStat::reset_range");
548 reset_bound(range.m_bound1);
549 reset_bound(range.m_bound2);
550 DBUG_VOID_RETURN;
551 }
552
553 int
convert_range(Range & range_f,const NdbRecord * key_record,const NdbIndexScanOperation::IndexBound * ib)554 NdbIndexStat::convert_range(Range& range_f,
555 const NdbRecord* key_record,
556 const NdbIndexScanOperation::IndexBound* ib)
557 {
558 DBUG_ENTER("NdbIndexStat::convert_range");
559 Bound& bound1_f = range_f.m_bound1;
560 Bound& bound2_f = range_f.m_bound2;
561 NdbIndexStatImpl::Bound& bound1 =
562 *(NdbIndexStatImpl::Bound*)bound1_f.m_impl;
563 NdbIndexStatImpl::Bound& bound2 =
564 *(NdbIndexStatImpl::Bound*)bound2_f.m_impl;
565 NdbIndexStatImpl::Range range(bound1, bound2);
566 if (m_impl.convert_range(range, key_record, ib) == -1)
567 DBUG_RETURN(-1);
568 DBUG_RETURN(0);
569 }
570
571 // stat
572
Stat(void * buffer)573 NdbIndexStat::Stat::Stat(void* buffer)
574 {
575 DBUG_ENTER("NdbIndexStat::Stat::Stat");
576 require(buffer != 0);
577 Uint8* buf = (Uint8*)buffer;
578 // stat impl
579 Uint8* buf1 = buf;
580 UintPtr ubuf1 = (UintPtr)buf1;
581 if (ubuf1 % 8 != 0)
582 buf1 += (8 - ubuf1 % 8);
583 new (buf1) NdbIndexStatImpl::Stat;
584 m_impl = (void*)buf1;
585 DBUG_VOID_RETURN;
586 }
587
588 int
query_stat(const Range & range_f,Stat & stat_f)589 NdbIndexStat::query_stat(const Range& range_f, Stat& stat_f)
590 {
591 DBUG_ENTER("NdbIndexStat::query_stat");
592 Bound& bound1_f = range_f.m_bound1;
593 Bound& bound2_f = range_f.m_bound2;
594 NdbIndexStatImpl::Bound& bound1 =
595 *(NdbIndexStatImpl::Bound*)bound1_f.m_impl;
596 NdbIndexStatImpl::Bound& bound2 =
597 *(NdbIndexStatImpl::Bound*)bound2_f.m_impl;
598 NdbIndexStatImpl::Range range(bound1, bound2);
599 #ifndef DBUG_OFF
600 const uint sz = 8000;
601 char buf[sz];
602 DBUG_PRINT("index_stat", ("lo: %s", bound1.m_bound.print(buf, sz)));
603 DBUG_PRINT("index_stat", ("hi: %s", bound2.m_bound.print(buf, sz)));
604 #endif
605 NdbIndexStatImpl::Stat& stat =
606 *(NdbIndexStatImpl::Stat*)stat_f.m_impl;
607 if (m_impl.query_stat(range, stat) == -1)
608 DBUG_RETURN(-1);
609 DBUG_RETURN(0);
610 }
611
612 void
get_empty(const Stat & stat_f,bool * empty)613 NdbIndexStat::get_empty(const Stat& stat_f, bool* empty)
614 {
615 DBUG_ENTER("NdbIndexStat::get_empty");
616 const NdbIndexStatImpl::Stat& stat =
617 *(const NdbIndexStatImpl::Stat*)stat_f.m_impl;
618 require(empty != 0);
619 *empty = stat.m_value.m_empty;
620 DBUG_PRINT("index_stat", ("empty:%d", *empty));
621 DBUG_VOID_RETURN;
622 }
623
624 void
get_rir(const Stat & stat_f,double * rir)625 NdbIndexStat::get_rir(const Stat& stat_f, double* rir)
626 {
627 DBUG_ENTER("NdbIndexStat::get_rir");
628 const NdbIndexStatImpl::Stat& stat =
629 *(const NdbIndexStatImpl::Stat*)stat_f.m_impl;
630 double x = stat.m_value.m_rir;
631 if (x < 1.0)
632 x = 1.0;
633 require(rir != 0);
634 *rir = x;
635 #ifndef DBUG_OFF
636 char buf[100];
637 sprintf(buf, "%.2f", *rir);
638 #endif
639 DBUG_PRINT("index_stat", ("rir:%s", buf));
640 DBUG_VOID_RETURN;
641 }
642
643 void
get_rpk(const Stat & stat_f,Uint32 k,double * rpk)644 NdbIndexStat::get_rpk(const Stat& stat_f, Uint32 k, double* rpk)
645 {
646 DBUG_ENTER("NdbIndexStat::get_rpk");
647 const NdbIndexStatImpl::Stat& stat =
648 *(const NdbIndexStatImpl::Stat*)stat_f.m_impl;
649 double x = stat.m_value.m_rir / stat.m_value.m_unq[k];
650 if (x < 1.0)
651 x = 1.0;
652 require(rpk != 0);
653 *rpk = x;
654 #ifndef DBUG_OFF
655 char buf[100];
656 sprintf(buf, "%.2f", *rpk);
657 #endif
658 DBUG_PRINT("index_stat", ("rpk[%u]:%s", k, buf));
659 DBUG_VOID_RETURN;
660 }
661
662 void
get_rule(const Stat & stat_f,char * buffer)663 NdbIndexStat::get_rule(const Stat& stat_f, char* buffer)
664 {
665 DBUG_ENTER("NdbIndexStat::get_rule");
666 const NdbIndexStatImpl::Stat& stat =
667 *(const NdbIndexStatImpl::Stat*)stat_f.m_impl;
668 require(buffer != 0);
669 BaseString::snprintf(buffer, RuleBufferBytes, "%s/%s/%s",
670 stat.m_rule[0], stat.m_rule[1], stat.m_rule[2]);
671 DBUG_VOID_RETURN;
672 }
673
674 // events and polling
675
676 int
create_sysevents(Ndb * ndb)677 NdbIndexStat::create_sysevents(Ndb* ndb)
678 {
679 DBUG_ENTER("NdbIndexStat::create_sysevents");
680 if (m_impl.create_sysevents(ndb) == -1)
681 DBUG_RETURN(-1);
682 DBUG_RETURN(0);
683 }
684
685 int
drop_sysevents(Ndb * ndb)686 NdbIndexStat::drop_sysevents(Ndb* ndb)
687 {
688 DBUG_ENTER("NdbIndexStat::drop_sysevents");
689 if (m_impl.drop_sysevents(ndb) == -1)
690 DBUG_RETURN(-1);
691 DBUG_RETURN(0);
692 }
693
694 int
check_sysevents(Ndb * ndb)695 NdbIndexStat::check_sysevents(Ndb* ndb)
696 {
697 DBUG_ENTER("NdbIndexStat::check_sysevents");
698 if (m_impl.check_sysevents(ndb) == -1)
699 DBUG_RETURN(-1);
700 DBUG_RETURN(0);
701 }
702
703 int
create_listener(Ndb * ndb)704 NdbIndexStat::create_listener(Ndb* ndb)
705 {
706 DBUG_ENTER("NdbIndexStat::create_listener");
707 if (m_impl.create_listener(ndb) == -1)
708 DBUG_RETURN(-1);
709 DBUG_RETURN(0);
710 }
711
712 int
execute_listener(Ndb * ndb)713 NdbIndexStat::execute_listener(Ndb* ndb)
714 {
715 DBUG_ENTER("NdbIndexStat::execute_listener");
716 if (m_impl.execute_listener(ndb) == -1)
717 DBUG_RETURN(-1);
718 DBUG_RETURN(0);
719 }
720
721 int
poll_listener(Ndb * ndb,int max_wait_ms)722 NdbIndexStat::poll_listener(Ndb* ndb, int max_wait_ms)
723 {
724 DBUG_ENTER("NdbIndexStat::poll_listener");
725 int ret = m_impl.poll_listener(ndb, max_wait_ms);
726 if (ret == -1)
727 DBUG_RETURN(-1);
728 DBUG_RETURN(ret);
729 }
730
731 int
next_listener(Ndb * ndb)732 NdbIndexStat::next_listener(Ndb* ndb)
733 {
734 DBUG_ENTER("NdbIndexStat::next_listener");
735 int ret = m_impl.next_listener(ndb);
736 if (ret == -1)
737 DBUG_RETURN(-1);
738 DBUG_RETURN(ret);
739 }
740
741 int
drop_listener(Ndb * ndb)742 NdbIndexStat::drop_listener(Ndb* ndb)
743 {
744 DBUG_ENTER("NdbIndexStat::drop_listener");
745 if (m_impl.drop_listener(ndb) == -1)
746 DBUG_RETURN(-1);
747 DBUG_RETURN(0);
748 }
749
750 // mem
751
Mem()752 NdbIndexStat::Mem::Mem()
753 {
754 }
755
~Mem()756 NdbIndexStat::Mem::~Mem()
757 {
758 }
759
760 void
set_mem_handler(Mem * mem)761 NdbIndexStat::set_mem_handler(Mem* mem)
762 {
763 m_impl.m_mem_handler = mem;
764 }
765
766 // get impl
767
768 NdbIndexStatImpl&
getImpl()769 NdbIndexStat::getImpl()
770 {
771 return m_impl;
772 }
773
774 // error
775
Error()776 NdbIndexStat::Error::Error()
777 {
778 line = 0;
779 extra = 0;
780 }
781
782 const NdbIndexStat::Error&
getNdbError() const783 NdbIndexStat::getNdbError() const
784 {
785 return m_impl.getNdbError();
786 }
787
788 class NdbOut&
operator <<(class NdbOut & out,const NdbIndexStat::Error & error)789 operator<<(class NdbOut& out, const NdbIndexStat::Error& error)
790 {
791 out << static_cast<const NdbError&>(error);
792 out << " (line " << error.line << ", extra " << error.extra << ")";
793 return out;
794 }
795