Files
secondo/Tests/bdbtest.cpp
2026-01-23 17:03:45 +08:00

293 lines
7.1 KiB
C++

/*
07.11.2004 M. Spiekermann
This is a simple test of the Berkeley-Db C++ API. It was
programmed in order to test the performance of Berkeley-DB
B-Trees.
It was observed that the PrefetchingIterator implemented in
Secondos SMI is much slower than the bulk retrieval, but it
does call the same bulk-retrieval APIs as in this code.
*/
#include "DbVersion.h"
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <db_cxx.h>
#include <assert.h>
#include <iostream>
#include <string>
#include "StopWatch.h"
#include <cstdlib>
using namespace std;
void
check_bdb_error(const int rc, DbEnv& bdb) {
if ( (rc == DB_SECONDARY_BAD)
|| (rc == EINVAL)
|| (rc == ENOMEM) )
{
bdb.err(rc, "cursor.get()");
}
}
int
main( int argc, char** argv )
{
if ( argc == 1 ) {
cout << endl;
cout << "Usage: " << argv[0] << " -mode [NUM_INSERT | NUM_FIND | BUFFER]"
<< endl
<< "Operational modes are listed below: " << endl
<< " -1 : Create B-Tree with key integer and insert NUM_INSERT data"
<< " records of size 100 b" << endl
<< " -2 : Retrieve randomly NUM_FIND of NUM_INSERT integers." << endl
<< " -3 : Scan database with cursor." << endl
<< " -4 : Scan BTREE database using bulk retrieval with buffer "
<< "size BUFFER kb" << endl
<< " -5 : Create a DB_RECNO database with NUM_INSERT entries"
<< " of size 100 b" << endl
<< " -6 : Scan RECNO database using bulk retrieval with buffer"
<< " size BUFFER kb." << endl;
cout << endl;
exit(1);
}
int param1 = 0;
int param2 = 0;
const int mode = -1 * atoi(argv[1]);
if ( (mode == 1) || (mode == 4) || (mode == 5) || (mode == 6) ) {
if (!(argc == 3)) {
cout << "Arguments not correct!" << endl;
exit(2);
}
param1 = atoi(argv[2]);
}
if ( mode == 2 ) {
if (!(argc == 4)) {
cout << "Arguments not correct!" << endl;
exit(2);
}
param1 = atoi(argv[2]);
param2 = atoi(argv[3]);
}
const int pageSize = 4096;
DbEnv bdb(DB_CXX_NO_EXCEPTIONS);
const int CACHE_SIZE = 300 * pageSize;
int SetCachesizeSuccess = bdb.set_cachesize( 0 ,CACHE_SIZE, 0 );
assert( !SetCachesizeSuccess );
//assert( !bdb.set_flags(DB_DIRECT_DB | DB_REGION_INIT, 1) );
int BDBopened = bdb.open( 0, DB_CREATE | DB_INIT_MPOOL, 0);
assert( !BDBopened );
cout << "Environment opened. Cache size: "
<< CACHE_SIZE << " bytes." << endl;
string HOME("bdb-performance-test");
string DATABASE("access-btree.db");
string DATABASE2("access-recno.db");
Db db1(&bdb, 0);
Db db2(&bdb, 0);
int DBsetPagesizeSuccess = db1.set_pagesize(4096);
assert( !DBsetPagesizeSuccess );
u_int32_t openFlags;
if ( mode==1 || mode==5 ) {
openFlags = DB_CREATE;
} else {
openFlags = DB_RDONLY;
}
int DBopenSuccess = db1.open( 0, (DATABASE).c_str(),
0, DB_BTREE, openFlags, 0664);
assert( !DBopenSuccess );
cout << "Database " << DATABASE << " opened." << endl;
DBopenSuccess = db2.open( 0, (DATABASE2).c_str(),
0, DB_RECNO, openFlags, 0664);
assert( !DBopenSuccess );
cout << "Database " << DATABASE << " opened." << endl;
const int recSize = 100;
char dummyRec[recSize];
StopWatch runTime;
const int TEST_MAX = param1;
if ( mode == 1 ) {
cout << "Inserting " << TEST_MAX
<< " integer values into DB_BTREE ..." << endl;
for ( int j=1 ; j < TEST_MAX; j++ ) {
Dbt key( (void*) &j, sizeof(int) );
Dbt data( (void*) dummyRec, recSize );
int DBputSuccess = db1.put(0, &key, &data, 0);
assert( !DBputSuccess );
} // end of for j ...
}
if ( mode == 5 ) {
cout << "Inserting " << TEST_MAX << " records of size "
<< recSize <<" into DB_RECNO ..." << endl;
for ( int j=1 ; j < TEST_MAX; j++ ) {
Dbt key( (void*) &j, sizeof(int) );
Dbt data( (void*) dummyRec, recSize );
int DBputSuccess = db2.put(0, &key, &data, 0);
assert( !DBputSuccess );
} // end of for j ...
}
if ( mode == 2 ) {
const int READ_MAX = param2;
cout << "Random access of " << READ_MAX << " items ..." << endl;
for ( int j=1 ; j < READ_MAX; j++ ) {
int keyval = (int)(TEST_MAX * 1.0 * rand() / (RAND_MAX + 1.0)) + 1;
//cout << keyval << ", ";
Dbt key( (void *) &(keyval), sizeof(int) );
Dbt data;
int DBgetSuccess = db1.get(0, &key, &data, 0);
assert( !DBgetSuccess );
}
}
if ( mode == 3 ) {
Dbc* cursor = 0;
int DBcursorSuccess = !db1.cursor(0, &cursor, 0);
assert( !DBcursorSuccess );
Dbt key;
Dbt data;
int rc = 0;
cout << "Scanning database " << DATABASE << "..." << endl;
while ( (rc = cursor->get(&key, &data, DB_NEXT)) == 0 ) {
}
check_bdb_error(rc, bdb);
cursor->close();
}
Dbc* cursor = 0;
int DBcursorSuccess = db1.cursor(0, &cursor, 0);
assert( !DBcursorSuccess );
Dbt key;
int rc = 0;
Dbt retdata;
Dbt buf;
size_t cBufLength = 1;
if ( mode==4 || mode==6 ) {
cBufLength = param1 * 1024;
cout << "Buffer for bulk retrieval set to "
<< cBufLength << " bytes." << endl;
}
char cBuf[cBufLength];
buf.set_data(cBuf);
buf.set_ulen(cBufLength);
buf.set_dlen(cBufLength);
buf.set_doff(0);
buf.set_flags(DB_DBT_USERMEM);
/*
if ( mode == 4 ) {
DBcursorSuccess = db1.cursor(0, &cursor, 0);
assert( !DBcursorSuccess );
cout << "Bulk retrieval of " << DATABASE << "..." << endl;
for (;;) {
//cerr << "Getting next bulk of data ..." << endl;
rc = cursor->get(&key, &buf, DB_MULTIPLE_KEY | DB_NEXT);
if ( rc != 0) {
//cerr << "finished!" << endl;
check_bdb_error(rc, bdb);
break;
}
int ctr = 0;
for ( DB_MULTIPLE_INIT( bufptr, &buf );; ) {
DB_MULTIPLE_KEY_NEXT( bufptr, &buf, retkey, retklen, retdata, retdlen );
if (bufptr == 0) {
//cerr << "Iterating buffer finished!" << endl;
break;
}
//cout << ctr << " - key, data: " << *((int*)retkey)
// << ", " << *((int*)retdata)<< endl;
//ctr++;
}
}
cursor->close();
}
*/
if ( mode == 6 ) {
DBcursorSuccess = !db2.cursor(0, &cursor, 0);
assert( DBcursorSuccess );
db_recno_t recno = 0;
cout << "Bulk retrieval of " << DATABASE2 << "..." << endl;
#if (DB_VERSION_REQUIRED(4,2))
for (;;) {
//cerr << "Getting next bulk of data ..." << endl;
rc = cursor->get(&key, &buf, DB_MULTIPLE_KEY | DB_NEXT);
if ( rc != 0) {
//cerr << "finished!" << endl;
check_bdb_error(rc, bdb);
break;
}
DbMultipleRecnoDataIterator it(buf);
while ( it.next(recno, retdata) ) {};
}
cursor->close();
#else
cout << "Not supported below version 4.2!" << endl;
#endif
}
bool t1 = db1.close(DB_NOSYNC);
assert (!t1);
t1 = db2.close(DB_NOSYNC);
assert ( !t1);
cout << "Time: " << runTime.diffTimes() << endl;
int BDBclosed = bdb.close(0);
assert( !BDBclosed );
}