static SINT64 get_parameter(const SCHAR** ptr) { /************************************** * * g e t _ p a r a m e t e r * ************************************** * * Functional description * Get a parameter (length is encoded), convert to internal form, * and return. * **************************************/ SSHORT l = *(*ptr)++; l += (*(*ptr)++) << 8; const SINT64 parameter = isc_portable_integer(reinterpret_cast<const ISC_UCHAR*>(*ptr), l); *ptr += l; return parameter; }
void Why::UtilInterface::getPerfCounters(Firebird::CheckStatusWrapper* status, Firebird::IAttachment* att, const char* countersSet, ISC_INT64* counters) { try { // Parse countersSet unsigned cntLink[TOTAL_COUNTERS]; memset(cntLink, 0xFF, sizeof cntLink); Firebird::string dupSet(countersSet); char* set = dupSet.begin(); char* save = NULL; const char* delim = " \t,;"; unsigned typeMask = 0; unsigned n = 0; UCHAR info[TOTAL_COUNTERS]; // will never use all, but do not care about few bytes UCHAR* pinfo = info; #ifdef WIN_NT #define strtok_r strtok_s #endif for (char* nm = strtok_r(set, delim, &save); nm; nm = strtok_r(NULL, delim, &save)) { Firebird::NoCaseString name(nm); for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (name == knownCounters[i].name) { if (cntLink[i] != ~0u) (Firebird::Arg::Gds(isc_random) << "Duplicated name").raise(); //report name & position cntLink[i] = n++; typeMask |= knownCounters[i].type; if (knownCounters[i].type == CNT_DB_INFO) *pinfo++ = knownCounters[i].code; goto found; } } (Firebird::Arg::Gds(isc_random) << "Unknown name").raise(); //report name & position found: ; } #ifdef WIN_NT #undef strtok_r #endif // Force reset counters memset(counters, 0, n * sizeof(ISC_INT64)); // Fill time counters if (typeMask & CNT_TIMER) { SINT64 tr = fb_utils::query_performance_counter() * 1000 / fb_utils::query_performance_frequency(); SINT64 uTime, sTime; fb_utils::get_process_times(uTime, sTime); for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (cntLink[i] == ~0u) continue; if (knownCounters[i].type == CNT_TIMER) { clock_t v = 0; switch(knownCounters[i].code) { case CNT_TIME_REAL: v = tr; break; case CNT_TIME_USER: v = uTime; break; case CNT_TIME_SYSTEM: v = sTime; break; default: fb_assert(false); break; } counters[cntLink[i]] = v; } } } // Fill DB counters if (typeMask & CNT_DB_INFO) { UCHAR buffer[BUFFER_LARGE]; att->getInfo(status, pinfo - info, info, sizeof(buffer), buffer); if (status->getState() & Firebird::IStatus::STATE_ERRORS) return; const UCHAR* p = buffer; while (true) { SINT64 v = 0; UCHAR ipb = *p++; switch (ipb) { case isc_info_reads: case isc_info_writes: case isc_info_marks: case isc_info_fetches: case isc_info_num_buffers: case isc_info_page_size: case isc_info_current_memory: case isc_info_max_memory: v = get_parameter(&p); break; case isc_info_end: goto parsed; case isc_info_error: { const SINT64 temp = isc_portable_integer(p, 2); fb_assert(temp <= MAX_SSHORT); p += temp + 2; continue; } default: (Firebird::Arg::Gds(isc_random) << "Unknown info code").raise(); //report char code } for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (knownCounters[i].type == CNT_DB_INFO && knownCounters[i].code == ipb) { if (cntLink[i] != ~0u) counters[cntLink[i]] = v; break; } } } parsed: ; } } catch (const Firebird::Exception& ex) { ex.stuffException(status); } }