📄 testoibasic.cpp
字号:
/* 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; either version 2 of the License, or (at your option) any later version. 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 unsigned m_batch; const char* m_bound; const char* m_case; bool m_collsp; bool m_core; const char* m_csname; CHARSET_INFO* m_cs; int m_die; bool m_dups; NdbDictionary::Object::FragmentType m_fragtype; unsigned m_subsubloop; const char* m_index; unsigned m_loop; bool m_msglock; bool m_nologging; bool m_noverify; unsigned m_pctnull; unsigned m_rows; unsigned m_samples; unsigned m_scanpar; unsigned m_scanstop; int m_seed; unsigned m_subloop; const char* m_table; unsigned m_threads; int m_v; // int for lint Opt() : m_batch(32), m_bound("01234"), m_case(0), m_collsp(false), m_core(false), m_csname("random"), m_cs(0), m_die(0), m_dups(false), m_fragtype(NdbDictionary::Object::FragUndefined), m_subsubloop(4), 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_scanpar(0), m_scanstop(0), m_seed(-1), m_subloop(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 << " -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 << " -scanpar N scan parallelism [" << d.m_scanpar << "]" << endl << " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl << " -subloop N subtest loop count [" << d.m_subloop << "]" << 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 unsignedurandom(unsigned n){ if (n == 0) return 0; unsigned i = random() % n; return i;}static intirandom(unsigned n){ if (n == 0) return 0; int i = random() % n; if (random() & 0x1) i = -i; return i;}static boolrandompct(unsigned pct){ if (pct == 0) return false; if (pct >= 100) return true; return urandom(100) < pct;}static unsignedrandom_coprime(unsigned n){ unsigned prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; unsigned count = sizeof(prime) / sizeof(prime[0]); if (n == 0) return 0; while (1) { unsigned i = urandom(count); if (n % prime[i] != 0) return prime[i]; }}// random re-sequence of 0...(n-1)struct Rsq { Rsq(unsigned n); unsigned next();private: unsigned m_n; unsigned m_i; unsigned m_start; unsigned m_prime;};Rsq::Rsq(unsigned n){ m_n = n; m_i = 0; m_start = urandom(n); m_prime = random_coprime(n);}unsignedRsq::next(){ assert(m_n != 0); return (m_start + m_i++ * m_prime) % m_n;}// log and error macrosstatic NdbMutex *ndbout_mutex = NULL;static unsigned getthrno();static const char*getthrstr(){ static char buf[20]; unsigned n = getthrno(); if (n == (unsigned)-1) strcpy(buf, ""); else { unsigned m = g_opt.m_threads < 10 ? 1 : g_opt.m_threads < 100 ? 2 : 3; sprintf(buf, "[%0*u] ", m, n); } return buf;}#define LLN(n, s) \ do { \ if ((n) > g_opt.m_v) break; \ if (g_opt.m_msglock) NdbMutex_Lock(ndbout_mutex); \ ndbout << getthrstr() << 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)// 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 Set;class Tmr;struct Par : public Opt { unsigned 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; } 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; } unsigned m_lno; unsigned m_slno; unsigned m_totrows; // value calculation unsigned m_range; unsigned m_pctrange; unsigned m_pctbrange; int m_bdir; // choice of key bool m_randomkey; // do verify after read bool m_verify; // deadlock possible bool m_deadlock; // abort percentabge unsigned m_abortpct; NdbOperation::LockMode m_lockmode; // scan options bool m_tupscan; bool m_ordered; bool m_descending; // timer location Par(const Opt& opt) : Opt(opt), m_no(0), m_con(0), m_tab(0), m_set(0), m_tmr(0), m_lno(0), m_slno(0), m_totrows(m_threads * m_rows), m_range(m_rows), m_pctrange(40), m_pctbrange(80), m_bdir(0), m_randomkey(false), m_verify(false), m_deadlock(false), m_abortpct(0), m_lockmode(NdbOperation::LM_Read), m_tupscan(false), m_ordered(false), m_descending(false) { }};static boolusetable(Par par, unsigned i){ return par.m_table == 0 || strchr(par.m_table, '0' + i) != 0;}static booluseindex(Par par, unsigned i){ return par.m_index == 0 || strchr(par.m_index, '0' + i) != 0;}static unsignedthrrow(Par par, unsigned j){ return par.m_threads * j + par.m_no;}static boolisthrrow(Par par, unsigned i){ return i % par.m_threads == par.m_no;}// timerstruct Tmr { void clr(); void on(); void off(unsigned cnt = 0); const char* time(); const char* pct(const Tmr& t1); const char* over(const Tmr& t1); NDB_TICKS m_on; unsigned m_ms; unsigned 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(unsigned 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;}// list of intsstruct Lst { Lst(); unsigned m_arr[1000]; unsigned m_cnt; void push(unsigned i); unsigned cnt() const; void reset();};Lst::Lst() : m_cnt(0){}voidLst::push(unsigned i){ assert(m_cnt < sizeof(m_arr)/sizeof(m_arr[0])); m_arr[m_cnt++] = i;}unsignedLst::cnt() const{ return m_cnt;}voidLst::reset(){ m_cnt = 0;}// character setsstatic const unsigned maxcsnumber = 512;static const unsigned maxcharcount = 32;static const unsigned maxcharsize = 4;static const unsigned maxxmulsize = 8;// single mb charstruct Chr { unsigned char m_bytes[maxcharsize]; unsigned char m_xbytes[maxxmulsize * maxcharsize]; unsigned 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; unsigned 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]; unsigned i = 0; unsigned miss1 = 0; unsigned miss2 = 0; unsigned miss3 = 0; unsigned miss4 = 0; while (i < maxcharcount) { unsigned char* bytes = m_chr[i].m_bytes; unsigned char* xbytes = m_chr[i].m_xbytes; unsigned& 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 (unsigned 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 (unsigned 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 (unsigned j = 0; j < xlen; j++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -