📄 xvltest.cc
字号:
/************************************************************************************************* * Test cases of Villa for C++ * Copyright (C) 2000-2003 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM 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 Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/#include <xvilla.h>#include <cstdlib>#include <cstdio>#include <cstring>#include <ctime>#include <iostream>#include <iomanip>extern "C" {#include <pthread.h>#include <unistd.h>#include <sys/types.h>}using namespace std;using namespace qdbm;/* global constants */const int RECBUFSIZ = 32;const int LRECMAX = 25;const int NIDXMAX = 64;const int LCNUM = 32;const int NCNUM = 32;/* struct for argument of threads */struct Mission { Villa* villa; int rnum; int id; bool printer;};/* global variables */const char* progname;/* function prototypes */int main(int argc, char** argv);void myterminate();void myunexpected();void usage();int runwrite(int argc, char** argv);int runread(int argc, char** argv);int runmulti(int argc, char** argv);int runmisc(int argc, char** argv);void pxdperror(const char* name, DBM_error &e);int myrand(void);int dowrite(const char* name, int rnum);int doread(const char* name);int domulti(const char* name, int rnum, int tnum);void* mtwriter(void* arg);int domisc(const char* name);/* main routine */int main(int argc, char** argv){ int rv; progname = argv[0]; set_terminate(myterminate); set_unexpected(myunexpected); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "multi")){ rv = runmulti(argc, argv); } else if(!strcmp(argv[1], "misc")){ rv = runmisc(argc, argv); } else { usage(); } return rv;}/* for debug */void myterminate(){ cout << progname << ": terminate" << endl; exit(1);}/* for debug */void myunexpected(){ cout << progname << ": unexpected" << endl; exit(1);}/* print the usage and exit */void usage(){ cerr << progname << ": test cases for Villa for C++" << endl; cerr << endl; cerr << "usage:" << endl; cerr << " " << progname << " write name rnum" << endl; cerr << " " << progname << " read name" << endl; cerr << " " << progname << " multi name rnum tnum" << endl; cerr << " " << progname << " misc name" << endl; exit(1);}/* parse arguments of write command */int runwrite(int argc, char** argv){ char *name, *rstr; int i, rnum, rv; name = 0; rstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv;}/* parse arguments of read command */int runread(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name); return rv;}/* parse arguments of multi command */int runmulti(int argc, char** argv){ char *name, *rstr, *tstr; int i, rnum, tnum, rv; name = 0; rstr = 0; tstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!tstr){ tstr = argv[i]; } else { usage(); } } if(!name || !rstr || !tstr) usage(); rnum = atoi(rstr); tnum = atoi(tstr); if(rnum < 1 || tnum < 1) usage(); rv = domulti(name, rnum, tnum); return rv;}/* parse arguments of misc command */int runmisc(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = domisc(name); return rv;}/* print an error message */void pxdperror(const char* name, DBM_error &e){ cerr << progname << ": " << name << ": " << e << endl;}/* pseudo random number generator */int myrand(void){ static int cnt = 0; if(cnt == 0) std::srand(std::time(NULL)); return (std::rand() * std::rand() + (std::rand() >> (sizeof(int) * 4)) + (cnt++)) & 0x7FFFFFFF;}/* do writing test */int dowrite(const char* name, int rnum){ int i, len; char buf[RECBUFSIZ]; cout << "<Writing Test>" << endl; cout << " name=" << name << " rnum=" << rnum << endl; cout << endl; Villa* villa = 0; bool err = false; try { // open the database villa = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); // roop for storing for(i = 1; i <= rnum; i++){ // set a buffer for a key and a value len = sprintf(buf, "%08d", i); // store a record into the database villa->put(buf, len, buf, len); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database villa->close(); cout << "ok" << endl << endl; } catch(Villa_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(villa) delete villa; return err ? 1 : 0;}/* do reading test */int doread(const char* name){ int i, rnum, len; char buf[RECBUFSIZ], *val; cout << "<Reading Test>" << endl; cout << " name=" << name << endl; cout << endl; Villa* villa = 0; bool err = false; try { // open the database villa = new Villa(name); // get the number of records rnum = villa->rnum(); // roop for retrieving for(i = 1; i <= rnum; i++){ // set a buffer for a key len = sprintf(buf, "%08d", i); // retrieve a record from the database val = villa->get(buf, len); free(val); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database villa->close(); cout << "ok" << endl << endl; } catch(Villa_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(villa) delete villa; return err ? 1 : 0;}/* do multi thread test */int domulti(const char* name, int rnum, int tnum){ Villa* villa; pthread_t* tids; bool* tsts; Mission* mss; Villa_error* ep; int i, len, size, vnum; bool err; char buf[RECBUFSIZ], *val; cout << "<Multi-thread Test>" << endl; cout << " name=" << name << " rnum=" << rnum << " tnum=" << tnum << endl; cout << endl; // open the database villa = 0; try { cout << "Creating a database ... "; villa = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); villa->settuning(LRECMAX, NIDXMAX, LCNUM, NCNUM); cout << "ok" << endl; } catch(Villa_error& e){ if(villa) delete villa; pxdperror(name, e); return 1; } // prepare threads tids = new pthread_t[tnum]; tsts = new bool[tnum]; mss = new Mission[tnum]; err = false; // roop for each threads cout << "Writing" << endl; for(i = 0; i < tnum; i++){ mss[i].villa = villa; mss[i].rnum = rnum; mss[i].id = i; mss[i].printer = (i == tnum / 2); if(pthread_create(tids + i, 0, mtwriter, (void*)(mss + i)) == 0){ tsts[i] = true; } else { tsts[i] = false; err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } // join every threads for(i = 0; i < tnum; i++){ if(tsts[i]){ if(pthread_join(tids[i], (void**)&ep) != 0){ err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } if(ep){ err = true; pxdperror(name, *ep); delete ep; } } delete[] mss; delete[] tsts; delete[] tids; if(!err) cout << "ok" << endl; cout.flush(); // check every record cout << "Validation checking ... "; try { for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); val = villa->get(buf, len, &size); free(val); if(size != 1){ cerr << progname << ": " << name << ": " << "size error: " << size << endl; err = true; } vnum = villa->vnum(buf, len); if(vnum != tnum){ cerr << progname << ": " << name << ": " << "vnum error: " << vnum << endl; err = true; } } } catch(Villa_error& e){ pxdperror(name, e); err = true; } if(!err) cout << "ok" << endl; // close the database cout << "Closing the database ... "; try { villa->close(); } catch(Villa_error& e){ pxdperror(name, e); delete villa; return 1; } cout << "ok" << endl; if(!err) cout << "all ok" << endl << endl; delete villa; return err ? 1 : 0;}/* writer with each thread */void* mtwriter(void* arg){ Mission* mp = (Mission*)arg; Villa* villa = mp->villa; int rnum = mp->rnum; int id = mp->id; bool printer = mp->printer; char buf[RECBUFSIZ]; void* mc; int i, len; // roop for storing for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); // store a record bool tran = false; try { if(myrand() % (mp->rnum / 7 + 1) == 0){ villa->tranbegin(); tran = true; } villa->put(buf, len, id % 2 ? "*" : "=", 1, Villa::DDUP); } catch(Villa_error& e){ if(tran) villa->tranabort(); return new Villa_error(e); } if(tran) villa->trancommit(); // print progression if(printer && rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } // malloc reentrant check if((mc = (char*)malloc(1)) != 0){ free(mc); } else { return new Villa_error(Villa::EALLOC); } } return 0;}/* do combination test */int domisc(const char* name){ bool err; int i, len; char buf[RECBUFSIZ]; cout << "<Miscellaneous Test>" << endl; cout << " name=" << name << endl; cout << endl; err = false; ADBM* adbm = 0; try { // open the database cout << "Creating a database ... "; adbm = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); cout << "ok" << endl; // write with datadase abstraction cout << "Writing with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); Datum val(buf, len); adbm->storerec(key, val, true); } cout << "ok" << endl; // read with datadase abstraction cout << "Reading with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); const Datum& val = adbm->fetchrec(key); len = val.size(); if(len != 8) throw DBM_error("size error"); } cout << "ok" << endl; // traversal access with database abstraction cout << "Traversal access with database abstraction ... "; i = 0; try { for(adbm->firstkey(); true; adbm->nextkey()){ i++; } } catch(DBM_error& e){ if(adbm->error()) throw; } if(i != 100) throw DBM_error("iteration error"); cout << "ok" << endl; // close the database cout << "Closing the database ... "; adbm->close(); cout << "ok" << endl; } catch(DBM_error& e){ err = true; pxdperror(name, e); } if(adbm) delete adbm; if(err) return 1; Villa* villa = 0; try { // open the database cout << "Opening the database ... "; villa = new Villa(name); cout << "ok" << endl; // traversal access cout << "Traversal access ... "; try { villa->curfirst(); for(i = 0; true; i++){ villa->curnext(); } if(i != 100) throw Villa_error(); } catch(Villa_error& e){ if(e != Villa::ENOITEM) throw; } cout << "ok" << endl; // checking information cout << "Checking information" << endl; cout << " - fsiz ... " << villa->fsiz() << endl; cout << " - lnum ... " << villa->lnum() << endl; cout << " - nnum ... " << villa->nnum() << endl; cout << " - rnum ... " << villa->rnum() << endl; cout << " - writable ... " << villa->writable() << endl; cout << " - fatalerror ... " << villa->fatalerror() << endl; cout << " - inode ... " << villa->inode() << endl; cout << "ok" << endl; // close the database cout << "Closing the database ... "; villa->close(); cout << "ok" << endl; } catch(Villa_error& e){ err = true; pxdperror(name, e); } if(villa) delete villa; if(err) return 1; villa = 0; try { // open the database cout << "Opening the database ... "; villa = new Villa(name, Villa::OWRITER); cout << "ok" << endl; // sync the database cout << "Syncing the database ... "; villa->sync(); cout << "ok" << endl; // optimize the database cout << "Optimizing the database ... "; villa->optimize(); cout << "ok" << endl; // close the database cout << "Closing the database ... "; villa->close(); cout << "ok" << endl; } catch(Villa_error& e){ err = true; pxdperror(name, e); } if(villa) delete villa; if(err) return 1; cout << "all ok" << endl << endl; return 0;}/* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -