19 #define DBTUX_STAT_CPP
27 Dbtux::execREAD_PSEUDO_REQ(
Signal* signal)
31 scanPtr.i = signal->theData[0];
32 c_scanOpPool.
getPtr(scanPtr);
34 statPtr.i = scanPtr.p->m_statOpPtrI;
36 Uint32 attrId = signal->theData[1];
37 Uint32* out = &signal->theData[0];
40 case AttributeHeader::RECORDS_IN_RANGE:
42 ndbrequire(statPtr.i == RNIL);
43 statRecordsInRange(scanPtr, out);
45 case AttributeHeader::INDEX_STAT_KEY:
47 ndbrequire(statPtr.i != RNIL);
48 c_statOpPool.
getPtr(statPtr);
49 statScanReadKey(statPtr, out);
51 case AttributeHeader::INDEX_STAT_VALUE:
53 ndbrequire(statPtr.i != RNIL);
54 c_statOpPool.
getPtr(statPtr);
55 statScanReadValue(statPtr, out);
76 Dbtux::statRecordsInRange(ScanOpPtr scanPtr, Uint32* out)
78 ScanOp& scan = *scanPtr.p;
79 Frag& frag = *c_fragPool.
getPtr(scan.m_fragPtrI);
80 const Index&
index = *c_indexPool.
getPtr(frag.m_indexId);
81 TreeHead& tree = frag.m_tree;
83 TreePos pos1 = scan.m_scanPos;
86 const unsigned idir = 1;
87 const ScanBound& scanBound = scan.m_scanBound[idir];
88 KeyDataC searchBoundData(index.m_keySpec,
true);
89 KeyBoundC searchBound(searchBoundData);
90 unpackBound(c_ctx, scanBound, searchBound);
91 searchToScan(frag, idir, searchBound, pos2);
93 ndbrequire(pos2.m_loc != NullTupLoc);
96 out[0] = (Uint32)frag.m_entryCount;
97 out[2] = getEntriesBeforeOrAfter(frag, pos1, 0);
98 out[3] = getEntriesBeforeOrAfter(frag, pos2, 1);
99 if (pos1.m_loc == pos2.m_loc) {
100 ndbrequire(pos2.m_pos >= pos1.m_pos);
101 out[1] = pos2.m_pos - pos1.m_pos + 1;
103 Uint32 rem = out[2] + out[3];
105 out[1] = out[0] - rem;
108 out[1] = tree.m_maxOccup;
120 Dbtux::getEntriesBeforeOrAfter(Frag& frag, TreePos pos,
unsigned idir)
122 NodeHandle node(frag);
123 selectNode(node, pos.m_loc);
124 Uint16 path[MaxTreeDepth + 1];
125 unsigned depth = getPathToNode(node, path);
126 ndbrequire(depth != 0 && depth <= MaxTreeDepth);
127 TreeHead& tree = frag.m_tree;
129 Uint32 tot = (Uint32)frag.m_entryCount;
132 while (
i + 1 < depth) {
133 unsigned occup2 = (path[
i] >> 8);
134 unsigned side = (path[
i + 1] & 0xFF);
136 tot = tot >= occup2 ? (tot - occup2) / 2 : 0;
145 unsigned occup = (path[
i] >> 8);
146 ndbrequire(pos.m_pos < occup);
149 cnt += pos.m_pos - 1;
151 cnt += occup - (pos.m_pos + 1);
154 tot = tot >= occup ? (tot - occup) / 2 : 0;
166 Dbtux::getPathToNode(NodeHandle node, Uint16* path)
168 TupLoc loc = node.m_loc;
169 unsigned i = MaxTreeDepth;
170 while (loc != NullTupLoc) {
172 selectNode(node, loc);
173 path[
i] = node.getSide() | (node.getOccup() << 8);
174 loc = node.getLink(2);
178 unsigned depth = MaxTreeDepth -
i;
181 path[j] = path[i + 1 + j];
194 return ::log(x) / ::log((
double)2.0);
198 Dbtux::statScanInit(StatOpPtr statPtr,
const Uint32* data, Uint32 len,
201 StatOp& stat = *statPtr.p;
202 ScanOp& scan = *c_scanOpPool.
getPtr(stat.m_scanOpPtrI);
203 Frag& frag = *c_fragPool.
getPtr(scan.m_fragPtrI);
204 const Index& index = *c_indexPool.
getPtr(scan.m_indexId);
208 stat.m_saveSize = c_indexStatSaveSize;
209 stat.m_saveScale = c_indexStatSaveScale;
211 while (offset + 1 <= len)
214 const Uint32 value = data[offset + 1];
216 case TuxBoundInfo::StatSaveSize:
218 stat.m_saveSize = value;
220 case TuxBoundInfo::StatSaveScale:
222 stat.m_saveScale = value;
226 scan.m_errorCode = TuxBoundInfo::InvalidBounds;
234 Uint32 avgKeyBytes = 0;
235 if (frag.m_entryCount != 0)
237 avgKeyBytes = (Uint32)(frag.m_entryBytes / frag.m_entryCount);
238 if (avgKeyBytes > stat.m_keySpec.get_max_data_len(
false))
239 avgKeyBytes = stat.m_keySpec.get_max_data_len(
false);
244 double a = stat.m_saveSize;
245 double b = stat.m_saveScale;
246 double c = avgKeyBytes;
247 double d = index.m_numAttrs;
248 double e = c + (1 + d) * 4;
249 double f = (double)frag.m_entryCount;
253 double h = 1 + 0.01 * b * tux_log2(g);
259 double l = e * f / k;
261 stat.m_batchSize = (Uint32)(k + 0.5);
262 stat.m_estBytes = (Uint32)(l + 0.5);
263 ndbrequire(stat.m_batchSize != 0);
264 D(
"computed batch size" << V(stat));
268 stat.m_keyCount = index.m_numAttrs;
269 stat.m_valueCount = 1 + stat.m_keyCount;
270 stat.m_keyData1.reset();
271 stat.m_keyData2.reset();
274 stat.m_valueCount = 1 + stat.m_keyCount;
279 int ret = valueSpec.add(type, stat.m_valueCount);
280 ndbrequire(ret == 0);
287 Dbtux::statScanAddRow(StatOpPtr statPtr, TreeEnt ent)
289 StatOp& stat = *statPtr.p;
290 ScanOp& scan = *c_scanOpPool.
getPtr(stat.m_scanOpPtrI);
291 Frag& frag = *c_fragPool.
getPtr(scan.m_fragPtrI);
292 D(
"statScanAddRow" << V(stat));
294 KeyData& keyData1 = stat.m_keyData1;
295 KeyData& keyData2 = stat.m_keyData2;
296 StatOp::Value& value1 = stat.m_value1;
297 StatOp::Value& value2 = stat.m_value2;
301 const bool firstRow = (stat.m_rowCount == 1);
306 ret = keyData1.copy(keyData2);
307 ndbrequire(ret == 0);
312 readKeyAttrs(c_ctx, frag, ent, keyData2, stat.m_keyCount);
315 value2.m_rir = stat.m_rowCount;
318 for (Uint32 i = 0; i < stat.m_keyCount; i++)
320 stat.m_keyChange =
false;
326 int res = keyData1.cmp(keyData2, stat.m_keyCount, num_eq);
327 ndbrequire(res <= 0);
328 stat.m_keyChange = (res != 0);
330 if (stat.m_keyChange)
332 ndbrequire(num_eq < stat.m_keyCount);
333 value2.m_unq[num_eq]++;
335 for (Uint32 i = num_eq + 1; i < stat.m_keyCount; i++)
341 bool lastEntry =
false;
344 NodeHandle node(frag);
345 TreePos pos = scan.m_scanPos;
346 selectNode(node, pos.m_loc);
348 const unsigned occup = node.getOccup();
350 if (pos.m_dir == 3 && pos.m_pos + (
unsigned)1 < occup)
356 if (node.getLink(1) != NullTupLoc)
362 while (node.getSide() == 1)
365 TupLoc loc = node.getLink(2);
366 selectNode(node, loc);
369 if (node.getSide() != 2)
378 stat.m_usePrev =
true;
382 stat.m_usePrev =
false;
385 if (stat.m_batchCurr >= stat.m_batchSize && stat.m_keyChange)
388 stat.m_batchCurr = 0;
395 Dbtux::statScanReadKey(StatOpPtr statPtr, Uint32* out)
397 StatOp& stat = *statPtr.p;
400 KeyData& keyData = stat.m_keyData;
401 ret = keyData.copy(stat.m_usePrev ? stat.m_keyData1 : stat.m_keyData2);
402 ndbrequire(ret == 0);
403 D(
"statScanReadKey" << V(keyData));
404 keyData.convert(NdbPack::Endian::Little);
405 memcpy(out, keyData.get_full_buf(), keyData.get_full_len());
409 Dbtux::statScanReadValue(StatOpPtr statPtr, Uint32* out)
411 StatOp& stat = *statPtr.p;
415 const StatOp::Value& value = stat.m_usePrev ? stat.m_value1 : stat.m_value2;
418 ndbrequire(value.m_rir != 0);
419 for (Uint32 k = 0; k < stat.m_keyCount; k++)
421 ndbrequire(value.m_unq[k] != 0);
422 ndbrequire(value.m_rir >= value.m_unq[k]);
423 ndbrequire(k == 0 || value.m_unq[k] >= value.m_unq[k - 1]);
429 ret = valueData.add(&value.m_rir, &len_out);
430 ndbrequire(ret == 0 && len_out == 4);
431 ret = valueData.add(&value.m_unq[0], stat.m_keyCount, &len_out);
432 ndbrequire(ret == 0 && len_out == stat.m_keyCount * 4);
433 ret = valueData.finalize();
434 ndbrequire(ret == 0);
436 D(
"statScanReadValue" << V(valueData));
437 valueData.convert(NdbPack::Endian::Little);
438 memcpy(out, valueData.get_full_buf(), valueData.get_full_len());
443 Dbtux::execINDEX_STAT_REP(
Signal* signal)
448 switch (rep->requestType) {
449 case IndexStatRep::RT_UPDATE_REQ:
452 case IndexStatRep::RT_UPDATE_CONF:
454 Index& index = *c_indexPool.
getPtr(rep->indexId);
456 findFrag(index, rep->fragId, fragPtr);
457 ndbrequire(fragPtr.i != RNIL);
459 D(
"loadTime" << V(index.m_statLoadTime) <<
" ->" << V(rep->loadTime));
460 index.m_statLoadTime = rep->loadTime;
472 Dbtux::execINDEX_STAT_IMPL_REQ(
Signal* signal)
477 StatMon& mon = c_statMon;
479 mon.m_requestType = req->requestType;
481 switch (mon.m_requestType) {
482 case IndexStatReq::RT_START_MON:
483 statMonStart(signal, mon);
485 case IndexStatReq::RT_STOP_MON:
486 statMonStop(signal, mon);
495 Dbtux::statMonStart(
Signal* signal, StatMon& mon)
498 Index& index = *c_indexPool.
getPtr(req->indexId);
499 D(
"statMonStart" << V(mon));
502 if (req->fragId == ZNIL)
505 index.m_statFragPtrI = RNIL;
506 D(
"non-monitoring node");
512 findFrag(index, req->fragId, fragPtr);
513 ndbrequire(fragPtr.i != RNIL);
514 index.m_statFragPtrI = fragPtr.i;
515 fragPtr.p->m_entryOps = 0;
516 D(
"monitoring node" << V(index));
519 statMonConf(signal, mon);
523 Dbtux::statMonStop(
Signal* signal, StatMon& mon)
526 Index& index = *c_indexPool.
getPtr(req->indexId);
527 D(
"statMonStop" << V(mon));
530 ndbrequire(req->fragId == ZNIL);
531 index.m_statFragPtrI = RNIL;
533 statMonConf(signal, mon);
537 Dbtux::statMonConf(
Signal* signal, StatMon& mon)
540 D(
"statMonConf" << V(mon));
543 conf->senderRef = reference();
544 conf->senderData = req->senderData;
545 sendSignal(req->senderRef, GSN_INDEX_STAT_IMPL_CONF,
546 signal, IndexStatImplConf::SignalLength, JBB);
552 Dbtux::statMonSendContinueB(
Signal* signal)
554 StatMon& mon = c_statMon;
555 D(
"statMonSendContinueB" << V(mon));
557 signal->theData[0] = TuxContinueB::StatMon;
558 signal->theData[1] = mon.m_loopIndexId;
559 sendSignalWithDelay(reference(), GSN_CONTINUEB,
560 signal, mon.m_loopDelay, 2);
564 Dbtux::statMonExecContinueB(
Signal* signal)
566 StatMon& mon = c_statMon;
567 D(
"statMonExecContinueB" << V(mon));
569 if (!c_indexStatAutoUpdate ||
570 c_indexStatTriggerPct == 0 ||
577 statMonCheck(signal, mon);
579 statMonSendContinueB(signal);
583 Dbtux::statMonCheck(
Signal* signal, StatMon& mon)
585 const Uint32 now = (Uint32)time(0);
586 D(
"statMonCheck" << V(mon) << V(now));
588 const uint maxloop = 32;
589 for (uint loop = 0; loop < maxloop; loop++, mon.m_loopIndexId++)
592 mon.m_loopIndexId %= c_indexPool.getSize();
594 const Index& index = *c_indexPool.
getPtr(mon.m_loopIndexId);
595 if (index.m_state == Index::NotDefined ||
596 index.m_state == Index::Dropping ||
597 index.m_statFragPtrI == RNIL)
602 const Frag& frag = *c_fragPool.
getPtr(index.m_statFragPtrI);
605 if (index.m_statLoadTime == 0)
609 D(
"statMonCheck" << V(update) << V(index.m_statLoadTime));
611 else if (now < index.m_statLoadTime + c_indexStatUpdateDelay)
615 D(
"statMonCheck" << V(update) << V(index.m_statLoadTime));
619 const Uint64 count = frag.m_entryCount;
620 const Uint64 ops = frag.m_entryOps;
625 D(
"statMonCheck" << V(update) << V(ops));
631 double a = c_indexStatTriggerPct;
632 double b = c_indexStatTriggerScale;
633 double c = (double)count;
634 double d = 1 + 0.01 * b * tux_log2(c);
636 double f = (double)ops;
637 double g = 100.0 * f / c;
639 D(
"statMonCheck" << V(update) << V(f) << V(c));
646 statMonRep(signal, mon);
655 Dbtux::statMonRep(
Signal* signal, StatMon& mon)
657 const Index& index = *c_indexPool.
getPtr(mon.m_loopIndexId);
658 const Frag& frag = *c_fragPool.
getPtr(index.m_statFragPtrI);
659 D(
"statMonRep" << V(mon));
662 rep->senderRef = reference();
663 rep->senderData = mon.m_loopIndexId;
664 rep->requestType = IndexStatRep::RT_UPDATE_REQ;
665 rep->requestFlag = 0;
666 rep->indexId = mon.m_loopIndexId;
667 rep->indexVersion = 0;
668 rep->tableId = index.m_tableId;
669 rep->fragId = frag.m_fragId;
670 rep->loadTime = index.m_statLoadTime;
672 sendSignal(DBDICT_REF, GSN_INDEX_STAT_REP,
673 signal, IndexStatRep::SignalLength, JBB);