testoibasic.cpp
来自「这个文件是windows mysql源码」· C++ 代码 · 共 2,845 行 · 第 1/5 页
CPP
2,845 行
/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * testOIBasic - ordered index test */#include <ndb_global.h>#include <NdbMain.h>#include <NdbOut.hpp>#include <NdbApi.hpp>#include <NdbTest.hpp>#include <NdbMutex.h>#include <NdbCondition.h>#include <NdbThread.h>#include <NdbTick.h>#include <NdbSleep.h>#include <my_sys.h>#include <NdbSqlUtil.hpp>#include <ndb_version.h>// optionsstruct Opt { // common options uint m_batch; const char* m_bound; const char* m_case; bool m_collsp; bool m_cont; bool m_core; const char* m_csname; CHARSET_INFO* m_cs; int m_die; bool m_dups; NdbDictionary::Object::FragmentType m_fragtype; const char* m_index; uint m_loop; bool m_msglock; bool m_nologging; bool m_noverify; uint m_pctnull; uint m_rows; uint m_samples; uint m_scanbatch; uint m_scanpar; uint m_scanstop; int m_seed; const char* m_skip; uint m_sloop; uint m_ssloop; const char* m_table; uint m_threads; int m_v; // int for lint Opt() : m_batch(32), m_bound("01234"), m_case(0), m_collsp(false), m_cont(false), m_core(false), m_csname("random"), m_cs(0), m_die(0), m_dups(false), m_fragtype(NdbDictionary::Object::FragUndefined), m_index(0), m_loop(1), m_msglock(true), m_nologging(false), m_noverify(false), m_pctnull(10), m_rows(1000), m_samples(0), m_scanbatch(0), m_scanpar(0), m_scanstop(0), m_seed(-1), m_skip(0), m_sloop(4), m_ssloop(4), m_table(0), m_threads(4), m_v(1) { }};static Opt g_opt;static void printcases();static void printtables();static voidprinthelp(){ Opt d; ndbout << "usage: testOIbasic [options]" << endl << " -batch N pk operations in batch [" << d.m_batch << "]" << endl << " -bound xyz use only these bound types 0-4 [" << d.m_bound << "]" << endl << " -case abc only given test cases (letters a-z)" << endl << " -collsp use strnncollsp instead of strnxfrm" << endl << " -cont on error continue to next test case [" << d.m_cont << "]" << endl << " -core core dump on error [" << d.m_core << "]" << endl << " -csname S charset or collation [" << d.m_csname << "]" << endl << " -die nnn exit immediately on NDB error code nnn" << endl << " -dups allow duplicate tuples from index scan [" << d.m_dups << "]" << endl << " -fragtype T fragment type single/small/medium/large" << endl << " -index xyz only given index numbers (digits 0-9)" << endl << " -loop N loop count full suite 0=forever [" << d.m_loop << "]" << endl << " -nologging create tables in no-logging mode" << endl << " -noverify skip index verifications" << endl << " -pctnull N pct NULL values in nullable column [" << d.m_pctnull << "]" << endl << " -rows N rows per thread [" << d.m_rows << "]" << endl << " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl << " -scanbatch N scan batch 0=default [" << d.m_scanbatch << "]" << endl << " -scanpar N scan parallel 0=default [" << d.m_scanpar << "]" << endl << " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl << " -skip abc skip given test cases (letters a-z)" << endl << " -sloop N level 2 (sub)loop count [" << d.m_sloop << "]" << endl << " -ssloop N level 3 (sub)loop count [" << d.m_ssloop << "]" << endl << " -table xyz only given table numbers (digits 0-9)" << endl << " -threads N number of threads [" << d.m_threads << "]" << endl << " -vN verbosity [" << d.m_v << "]" << endl << " -h or -help print this help text" << endl ; printcases(); printtables();}// not yet configurablestatic const bool g_store_null_key = true;// compare NULL like normal value (NULL < not NULL, NULL == NULL)static const bool g_compare_null = true;static const char* hexstr = "0123456789abcdef";// random intsstatic uinturandom(uint n){ if (n == 0) return 0; uint i = random() % n; return i;}static intirandom(uint n){ if (n == 0) return 0; int i = random() % n; if (random() & 0x1) i = -i; return i;}static boolrandompct(uint pct){ if (pct == 0) return false; if (pct >= 100) return true; return urandom(100) < pct;}static uintrandom_coprime(uint n){ uint prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; uint count = sizeof(prime) / sizeof(prime[0]); if (n == 0) return 0; while (1) { uint i = urandom(count); if (n % prime[i] != 0) return prime[i]; }}// random re-sequence of 0...(n-1)struct Rsq { Rsq(uint n); uint next();private: uint m_n; uint m_i; uint m_start; uint m_prime;};Rsq::Rsq(uint n){ m_n = n; m_i = 0; m_start = urandom(n); m_prime = random_coprime(n);}uintRsq::next(){ assert(m_n != 0); return (m_start + m_i++ * m_prime) % m_n;}// log and error macrosstatic NdbMutex *ndbout_mutex = NULL;static const char* getthrprefix();#define LLN(n, s) \ do { \ if ((n) > g_opt.m_v) break; \ if (g_opt.m_msglock) NdbMutex_Lock(ndbout_mutex); \ ndbout << getthrprefix(); \ if ((n) > 2) \ ndbout << "line " << __LINE__ << ": "; \ ndbout << s << endl; \ if (g_opt.m_msglock) NdbMutex_Unlock(ndbout_mutex); \ } while(0)#define LL0(s) LLN(0, s)#define LL1(s) LLN(1, s)#define LL2(s) LLN(2, s)#define LL3(s) LLN(3, s)#define LL4(s) LLN(4, s)#define LL5(s) LLN(5, s)#define HEX(x) hex << (x) << dec// following check a condition and return -1 on failure#undef CHK // simple check#undef CHKTRY // check with action on fail#undef CHKCON // print NDB API errors on failure#define CHK(x) CHKTRY(x, ;)#define CHKTRY(x, act) \ do { \ if (x) break; \ LL0("line " << __LINE__ << ": " << #x << " failed"); \ if (g_opt.m_core) abort(); \ act; \ return -1; \ } while (0)#define CHKCON(x, con) \ do { \ if (x) break; \ LL0("line " << __LINE__ << ": " << #x << " failed"); \ (con).printerror(ndbout); \ if (g_opt.m_core) abort(); \ return -1; \ } while (0)// method parametersclass Thr;class Con;class Tab;class ITab;class Set;class Tmr;struct Par : public Opt { uint m_no; Con* m_con; Con& con() const { assert(m_con != 0); return *m_con; } const Tab* m_tab; const Tab& tab() const { assert(m_tab != 0); return *m_tab; } const ITab* m_itab; const ITab& itab() const { assert(m_itab != 0); return *m_itab; } Set* m_set; Set& set() const { assert(m_set != 0); return *m_set; } Tmr* m_tmr; Tmr& tmr() const { assert(m_tmr != 0); return *m_tmr; } char m_currcase[2]; uint m_lno; uint m_slno; uint m_totrows; // value calculation uint m_range; uint m_pctrange; uint m_pctbrange; int m_bdir; bool m_noindexkeyupdate; // choice of key bool m_randomkey; // do verify after read bool m_verify; // errors to catch (see Con) bool m_catcherr; // abort percentage uint m_abortpct; NdbOperation::LockMode m_lockmode; // scan options bool m_tupscan; bool m_ordered; bool m_descending; // threads used by current test case uint m_usedthreads; Par(const Opt& opt) : Opt(opt), m_no(0), m_con(0), m_tab(0), m_itab(0), m_set(0), m_tmr(0), m_lno(0), m_slno(0), m_totrows(0), m_range(m_rows), m_pctrange(40), m_pctbrange(80), m_bdir(0), m_noindexkeyupdate(false), m_randomkey(false), m_verify(false), m_catcherr(0), m_abortpct(0), m_lockmode(NdbOperation::LM_Read), m_tupscan(false), m_ordered(false), m_descending(false), m_usedthreads(0) { m_currcase[0] = 0; }};static boolusetable(Par par, uint i){ return par.m_table == 0 || strchr(par.m_table, '0' + i) != 0;}static booluseindex(Par par, uint i){ return par.m_index == 0 || strchr(par.m_index, '0' + i) != 0;}static uintthrrow(Par par, uint j){ return par.m_usedthreads * j + par.m_no;}static boolisthrrow(Par par, uint i){ return i % par.m_usedthreads == par.m_no;}// timerstruct Tmr { void clr(); void on(); void off(uint cnt = 0); const char* time(); const char* pct(const Tmr& t1); const char* over(const Tmr& t1); NDB_TICKS m_on; uint m_ms; uint m_cnt; char m_time[100]; char m_text[100]; Tmr() { clr(); }};voidTmr::clr(){ m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;}voidTmr::on(){ assert(m_on == 0); m_on = NdbTick_CurrentMillisecond();}voidTmr::off(uint cnt){ NDB_TICKS off = NdbTick_CurrentMillisecond(); assert(m_on != 0 && off >= m_on); m_ms += off - m_on; m_cnt += cnt; m_on = 0;}const char*Tmr::time(){ if (m_cnt == 0) { sprintf(m_time, "%u ms", m_ms); } else { sprintf(m_time, "%u ms per %u ( %u ms per 1000 )", m_ms, m_cnt, (1000 * m_ms) / m_cnt); } return m_time;}const char*Tmr::pct(const Tmr& t1){ if (0 < t1.m_ms) { sprintf(m_text, "%u pct", (100 * m_ms) / t1.m_ms); } else { sprintf(m_text, "[cannot measure]"); } return m_text;}const char*Tmr::over(const Tmr& t1){ if (0 < t1.m_ms) { if (t1.m_ms <= m_ms) sprintf(m_text, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms); else sprintf(m_text, "-%u pct", (100 * (t1.m_ms - m_ms)) / t1.m_ms); } else { sprintf(m_text, "[cannot measure]"); } return m_text;}// character setsstatic const uint maxcsnumber = 512;static const uint maxcharcount = 32;static const uint maxcharsize = 4;static const uint maxxmulsize = 8;// single mb charstruct Chr { uchar m_bytes[maxcharsize]; uchar m_xbytes[maxxmulsize * maxcharsize]; uint m_size; Chr();};Chr::Chr(){ memset(m_bytes, 0, sizeof(m_bytes)); memset(m_xbytes, 0, sizeof(m_xbytes)); m_size = 0;}// charset and random valid chars to usestruct Chs { CHARSET_INFO* m_cs; uint m_xmul; Chr* m_chr; Chs(CHARSET_INFO* cs); ~Chs();};static NdbOut&operator<<(NdbOut& out, const Chs& chs);Chs::Chs(CHARSET_INFO* cs) : m_cs(cs){ m_xmul = m_cs->strxfrm_multiply; if (m_xmul == 0) m_xmul = 1; assert(m_xmul <= maxxmulsize); m_chr = new Chr [maxcharcount]; uint i = 0; uint miss1 = 0; uint miss2 = 0; uint miss3 = 0; uint miss4 = 0; while (i < maxcharcount) { uchar* bytes = m_chr[i].m_bytes; uchar* xbytes = m_chr[i].m_xbytes; uint& size = m_chr[i].m_size; bool ok; size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1); assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen); // prefer longer chars if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0) continue; for (uint j = 0; j < size; j++) { bytes[j] = urandom(256); } int not_used; // check wellformed const char* sbytes = (const char*)bytes; if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + size, 1, ¬_used) != size) { miss1++; continue; } // check no proper prefix wellformed ok = true; for (uint j = 1; j < size; j++) { if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) == j) { ok = false; break; } } if (!ok) { miss2++; continue; } // normalize memset(xbytes, 0, sizeof(xbytes)); // currently returns buffer size always int xlen = (*cs->coll->strnxfrm)(cs, xbytes, m_xmul * size, bytes, size); // check we got something ok = false; for (uint j = 0; j < xlen; j++) { if (xbytes[j] != 0) { ok = true; break; } } if (!ok) { miss3++; continue; } // check for duplicate (before normalize) ok = true; for (uint j = 0; j < i; j++) { const Chr& chr = m_chr[j]; if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) { ok = false; break; } } if (!ok) { miss4++; continue; } i++; } bool disorder = true; uint bubbles = 0; while (disorder) { disorder = false; for (uint i = 1; i < maxcharcount; i++) { uint len = sizeof(m_chr[i].m_xbytes); if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) { Chr chr = m_chr[i];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?