mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-11-16 09:06:25 +00:00
1088 lines
29 KiB
C++
1088 lines
29 KiB
C++
/*-
|
|
* See the file LICENSE for redistribution information.
|
|
*
|
|
* Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include "StlAdvancedFeatures.h"
|
|
|
|
static void usage();
|
|
|
|
class StlAdvancedFeaturesExample
|
|
{
|
|
public:
|
|
typedef map<int, int> m_int_t;
|
|
typedef ptint tpint;
|
|
~StlAdvancedFeaturesExample();
|
|
StlAdvancedFeaturesExample(void *param1);
|
|
void run()
|
|
{
|
|
arbitrary_object_storage();
|
|
storing_std_strings();
|
|
secondary_containers();
|
|
char_star_string_storage();
|
|
arbitray_sequence_storage();
|
|
bulk_retrieval_read();
|
|
primitive();
|
|
queue_stack();
|
|
}
|
|
private:
|
|
|
|
// Store primitive types of data into dbstl containers.
|
|
void primitive();
|
|
|
|
// Use std::queue and std::stack as adapters, and dbstl::db_vector
|
|
// as container, to make a queue and a stack.
|
|
void queue_stack();
|
|
|
|
// Use two ways to store an object of arbitrary length. The object
|
|
// contains some varying length members, char* string for example.
|
|
void arbitrary_object_storage();
|
|
|
|
// Store std::string types of strings.
|
|
void storing_std_strings();
|
|
|
|
// Open a secondary db H and associate it with an exisitng db handle
|
|
// which is being used by a container C1, then use H to create another
|
|
// container C2, verify we can get C1's data via C2.
|
|
// This technique works for all types of db and containers.
|
|
void secondary_containers();
|
|
|
|
// Direct storage of char* strings.
|
|
void char_star_string_storage();
|
|
|
|
// Storage of arbitrary element type of sequence.
|
|
void arbitray_sequence_storage();
|
|
|
|
// Reading with bulk retrieval flag.
|
|
void bulk_retrieval_read();
|
|
|
|
|
|
int flags, setflags, explicit_txn, test_autocommit, n;
|
|
DBTYPE dbtype;
|
|
dm_int_t::difference_type oddcnt;
|
|
Db *db3, *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1,
|
|
*dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv, *pquedb, *quedb;
|
|
Db *dbp3;
|
|
Db *dmdb6;
|
|
Db *dbp3sec;
|
|
Db *dmmdb4, *dbstrmap;
|
|
Db *dmstringdb;
|
|
Db *dbprim;
|
|
DbEnv *penv;
|
|
u_int32_t dboflags;
|
|
|
|
map<int, int> m1;
|
|
multimap<int, int> mm1;
|
|
};
|
|
|
|
StlAdvancedFeaturesExample::~StlAdvancedFeaturesExample()
|
|
{
|
|
}
|
|
|
|
StlAdvancedFeaturesExample::StlAdvancedFeaturesExample(void *param1)
|
|
{
|
|
check_expr(param1 != NULL);
|
|
TestParam *param = (TestParam*)param1;
|
|
TestParam *ptp = param;
|
|
|
|
flags = 0, setflags = 0, explicit_txn = 1, test_autocommit = 0;
|
|
dbtype = DB_BTREE;
|
|
penv = param->dbenv;
|
|
dmdb1 = dmdb2 = dmmdb1 = dmmdb2 = dmsdb1 = dmsdb2 = dmmsdb1 =
|
|
dmmsdb2 = dbstrv = NULL;
|
|
flags = param->flags;
|
|
dbtype = param->dbtype;
|
|
setflags = param->setflags;
|
|
test_autocommit = param->test_autocommit;
|
|
explicit_txn = param->explicit_txn;
|
|
dboflags = ptp->dboflags;
|
|
n = 10;
|
|
|
|
dmdb1 = dbstl::open_db(penv, "db_map.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
dmdb2 = dbstl::open_db(penv, "db_map2.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
dmdb6 = dbstl::open_db(penv, "db_map6.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
|
|
dmmdb1 = dbstl::open_db(penv,
|
|
"db_multimap.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
|
|
dmmdb2 = dbstl::open_db(penv,
|
|
"db_multimap2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
|
|
|
|
dmsdb1 = dbstl::open_db(penv, "db_set.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
dmsdb2 = dbstl::open_db(penv, "db_set2.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
|
|
dmmsdb1 = dbstl::open_db(penv,
|
|
"db_multiset.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
|
|
dmmsdb2 = dbstl::open_db(penv,
|
|
"db_multiset2.db", dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
|
|
|
|
dbstrv = dbstl::open_db(penv, "dbstr.db",
|
|
DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER);
|
|
dbp3sec = dbstl::open_db(penv, "db_map_sec.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, DB_DUP);
|
|
|
|
dmmdb4 = dbstl::open_db(penv,
|
|
"db_multimap4.db", dbtype, DB_CREATE | dboflags, DB_DUPSORT);
|
|
dbstrmap = dbstl::open_db(penv, "dbstrmap.db",
|
|
DB_BTREE, DB_CREATE, 0);
|
|
|
|
dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db",
|
|
dbtype, DB_CREATE | dboflags, 0);
|
|
db3 = dbstl::open_db(penv, "db3.db",
|
|
DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER);
|
|
|
|
// NO DB_RENUMBER needed
|
|
quedb = dbstl::open_db(penv, "dbquedb.db",
|
|
DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, 0);
|
|
|
|
pquedb = dbstl::open_db(penv, "dbpquedb.db",
|
|
DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, DB_RENUMBER);
|
|
dbprim = dbstl::open_db(penv, "dbprim.db",
|
|
DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, DB_RENUMBER);
|
|
|
|
dbp3 = dbstl::open_db(penv, "dbp3.db",
|
|
dbtype, DB_CREATE | ptp->dboflags, 0);
|
|
|
|
}
|
|
|
|
void StlAdvancedFeaturesExample::arbitrary_object_storage()
|
|
{
|
|
int i;
|
|
|
|
if (explicit_txn)
|
|
begin_txn(0, penv);
|
|
// varying length objects test
|
|
cout<<"\nArbitary object storage using Dbt..\n";
|
|
|
|
rand_str_dbt smsdbt;
|
|
DbstlDbt dbt, dbtmsg;
|
|
string msgstr;
|
|
SMSMsg *smsmsgs[10];
|
|
|
|
dbtmsg.set_flags(DB_DBT_USERMEM);
|
|
dbt.set_data(DbstlMalloc(256));
|
|
dbt.set_flags(DB_DBT_USERMEM);
|
|
dbt.set_ulen(256);
|
|
db_map<int, DbstlDbt> msgmap(dbp3, penv);
|
|
for (i = 0; i < 10; i++) {
|
|
smsdbt(dbt, msgstr, 10, 200);
|
|
SMSMsg *pmsg = SMSMsg::make_sms_msg(time(NULL),
|
|
(char *)dbt.get_data(), i);
|
|
smsmsgs[i] = SMSMsg::make_sms_msg(time(NULL),
|
|
(char *)dbt.get_data(), i);
|
|
dbtmsg.set_data(pmsg);
|
|
dbtmsg.set_ulen((u_int32_t)(pmsg->mysize));
|
|
dbtmsg.set_size((u_int32_t)(pmsg->mysize));
|
|
dbtmsg.set_flags(DB_DBT_USERMEM);
|
|
msgmap.insert(make_pair(i, dbtmsg));
|
|
free(pmsg);
|
|
memset(&dbtmsg, 0, sizeof(dbtmsg));
|
|
}
|
|
dbtmsg.set_data(NULL);
|
|
|
|
SMSMsg *psmsmsg;
|
|
for (i = 0; i < 10; i++) {
|
|
db_map<int, DbstlDbt>::data_type_wrap msgref = msgmap[i];
|
|
psmsmsg = (SMSMsg *)msgref.get_data();
|
|
check_expr(memcmp(smsmsgs[i], psmsmsg,
|
|
smsmsgs[i]->mysize) == 0);
|
|
}
|
|
|
|
i = 0;
|
|
for (db_map<int, DbstlDbt>::iterator msgitr =
|
|
msgmap.begin(ReadModifyWriteOption::
|
|
read_modify_write()); msgitr != msgmap.end(); ++msgitr, i++) {
|
|
db_map<int, DbstlDbt>::reference smsmsg = *msgitr;
|
|
(((SMSMsg*)(smsmsg.second.get_data())))->when = time(NULL);
|
|
smsmsg.second._DB_STL_StoreElement();
|
|
|
|
}
|
|
|
|
for (i = 0; i < 10; i++)
|
|
free(smsmsgs[i]);
|
|
|
|
msgmap.clear();
|
|
|
|
|
|
cout<<"\nArbitary object(sparse, varying length) storage support using registered callbacks.\n";
|
|
db_map<int, SMSMsg2> msgmap2(dbp3, penv);
|
|
SMSMsg2 smsmsgs2[10];
|
|
DbstlElemTraits<SMSMsg2>::instance()->set_copy_function(SMSMsgCopy);
|
|
DbstlElemTraits<SMSMsg2>::instance()->set_size_function(SMSMsgSize);
|
|
DbstlElemTraits<SMSMsg2>::instance()->set_restore_function(SMSMsgRestore);
|
|
// use new technique to store varying length and inconsecutive objs
|
|
for (i = 0; i < 10; i++) {
|
|
smsdbt(dbt, msgstr, 10, 200);
|
|
SMSMsg2 msg2(time(NULL), msgstr.c_str(), i);
|
|
smsmsgs2[i] = msg2;
|
|
|
|
msgmap2.insert(make_pair(i, msg2));
|
|
|
|
}
|
|
|
|
// check that retrieved data is identical to stored data
|
|
SMSMsg2 tmpmsg2;
|
|
for (i = 0; i < 10; i++) {
|
|
tmpmsg2 = msgmap2[i];
|
|
check_expr(smsmsgs2[i] == tmpmsg2);
|
|
}
|
|
for (db_map<int, SMSMsg2>::iterator msgitr =
|
|
msgmap2.begin(ReadModifyWriteOption::
|
|
read_modify_write()); msgitr != msgmap2.end(); msgitr++) {
|
|
db_map<int, SMSMsg2>::reference smsmsg = *msgitr;
|
|
smsmsg.second.when = time(NULL);
|
|
smsmsg.second._DB_STL_StoreElement();
|
|
|
|
}
|
|
msgmap2.clear();
|
|
if (explicit_txn)
|
|
commit_txn(penv);
|
|
} // arbitrary_object_storage
|
|
|
|
// std::string persistent test.
|
|
void StlAdvancedFeaturesExample::storing_std_strings()
|
|
{
|
|
string kstring = "hello world", *sstring = new string("hi there");
|
|
if (explicit_txn)
|
|
begin_txn(0, penv);
|
|
|
|
db_map<string, string> pmap(dmstringdb, NULL);
|
|
|
|
pmap[kstring] = *sstring + "!";
|
|
*sstring = pmap[kstring];
|
|
map<string, string> spmap;
|
|
spmap.insert(make_pair(kstring, *sstring));
|
|
cout<<"sstring append ! is : "<<pmap[kstring]
|
|
<<" ; *sstring is : "<<*sstring;
|
|
delete sstring;
|
|
for (db_map<string, string>::iterator ii = pmap.begin();
|
|
ii != pmap.end();
|
|
++ii) {
|
|
cout << (*ii).first << ": " << (*ii).second << endl;
|
|
}
|
|
close_db(dmstringdb);
|
|
|
|
dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db",
|
|
dbtype, DB_CREATE | dboflags, 0);
|
|
db_map<string, string> pmap2(dmstringdb, NULL);
|
|
for (db_map<string, string>::iterator ii = pmap2.begin();
|
|
ii != pmap2.end(); ++ii) {
|
|
cout << (*ii).first << ": " << (*ii).second << endl;
|
|
// assert key/data pair set equal
|
|
check_expr((spmap.count(ii->first) == 1) &&
|
|
(spmap[ii->first] == ii->second));
|
|
}
|
|
if (explicit_txn)
|
|
commit_txn(penv);
|
|
|
|
db_vector<string> strvctor(10);
|
|
vector<string> sstrvctor(10);
|
|
for (int i = 0; i < 10; i++) {
|
|
strvctor[i] = "abc";
|
|
sstrvctor[i] = strvctor[i];
|
|
}
|
|
check_expr(is_equal(strvctor, sstrvctor));
|
|
}
|
|
|
|
void StlAdvancedFeaturesExample::secondary_containers()
|
|
{
|
|
int i;
|
|
|
|
if (explicit_txn)
|
|
begin_txn(0, penv);
|
|
// test secondary db
|
|
cout<<"\ndb container backed by secondary database.";
|
|
|
|
dbp3->associate(dbstl::current_txn(penv), dbp3sec,
|
|
get_dest_secdb_callback, DB_CREATE);
|
|
typedef db_multimap<int, BaseMsg> sec_mmap_t;
|
|
sec_mmap_t secmmap(dbp3sec, penv);// index "to" field
|
|
db_map<int, BaseMsg> basemsgs(dbp3, penv);
|
|
basemsgs.clear();
|
|
BaseMsg tmpmsg;
|
|
multiset<BaseMsg> bsmsgs, bsmsgs2;
|
|
multiset<BaseMsg>::iterator bsitr1, bsitr2;
|
|
// populate primary and sec db
|
|
for (i = 0; i < 10; i++) {
|
|
tmpmsg.when = time(NULL);
|
|
tmpmsg.to = 100 - i % 3;// sec index multiple
|
|
tmpmsg.from = i + 20;
|
|
bsmsgs.insert( tmpmsg);
|
|
basemsgs.insert(make_pair(i, tmpmsg));
|
|
|
|
}
|
|
check_expr(basemsgs.size() == 10);
|
|
// check retrieved data is identical to those fed in
|
|
sec_mmap_t::iterator itrsec;
|
|
for (itrsec = secmmap.begin(
|
|
ReadModifyWriteOption::no_read_modify_write(), true);
|
|
itrsec != secmmap.end(); itrsec++) {
|
|
bsmsgs2.insert(itrsec->second);
|
|
}
|
|
for (bsitr1 = bsmsgs.begin(), bsitr2 = bsmsgs2.begin();
|
|
bsitr1 != bsmsgs.end() && bsitr2 != bsmsgs2.end();
|
|
bsitr1++, bsitr2++) {
|
|
check_expr(*bsitr1 == *bsitr2);
|
|
}
|
|
check_expr(bsitr1 == bsmsgs.end() && bsitr2 == bsmsgs2.end());
|
|
|
|
// search using sec index, check the retrieved data is expected
|
|
// and exists in bsmsgs
|
|
check_expr(secmmap.size() == 10);
|
|
pair<sec_mmap_t::iterator, sec_mmap_t::iterator> secrg =
|
|
secmmap.equal_range(98);
|
|
|
|
for (itrsec = secrg.first; itrsec != secrg.second; itrsec++) {
|
|
check_expr(itrsec->second.to == 98 &&
|
|
bsmsgs.count(itrsec->second) > 0);
|
|
}
|
|
// delete via sec db
|
|
size_t nersd = secmmap.erase(98);
|
|
check_expr(10 - nersd == basemsgs.size());
|
|
secrg = secmmap.equal_range(98);
|
|
check_expr(secrg.first == secrg.second);
|
|
|
|
if (explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
|
|
} // secondary_containers
|
|
|
|
void StlAdvancedFeaturesExample::char_star_string_storage()
|
|
{
|
|
int i;
|
|
// Varying length data element storage/retrieval
|
|
cout<<"\nchar*/wchar_t* string storage support...\n";
|
|
|
|
if (explicit_txn)
|
|
dbstl::begin_txn(0, penv);
|
|
// Use Dbt to wrap any object and store them. This is rarely needed,
|
|
// so this piece of code is only for test purpose.
|
|
db_vector<DbstlDbt> strv(dbstrv, penv);
|
|
vector<string> strsv;
|
|
vector<DbstlDbt> strvdbts;
|
|
strv.clear();
|
|
|
|
int strlenmax = 256, strlenmin = 64;
|
|
string str;
|
|
DbstlDbt dbt;
|
|
rand_str_dbt rand_str_maker;
|
|
dbt.set_flags(DB_DBT_USERMEM);
|
|
dbt.set_data(DbstlMalloc(strlenmax + 10));
|
|
dbt.set_ulen(strlenmax + 10);
|
|
|
|
for (int jj = 0; jj < 10; jj++) {
|
|
rand_str_maker(dbt, str, strlenmin, strlenmax);
|
|
strsv.push_back(str);
|
|
strv.push_back(dbt);
|
|
}
|
|
|
|
cout<<"\nstrings:\n";
|
|
for (i = 0; i < 10; i++) {
|
|
db_vector<DbstlDbt>::value_type_wrap elemref = strv[i];
|
|
strvdbts.push_back(elemref);
|
|
printf("\n%s\n%s", (char*)(strvdbts[i].get_data()),
|
|
strsv[i].c_str());
|
|
check_expr(strcmp((char*)(elemref.get_data()),
|
|
strsv[i].c_str()) == 0);
|
|
check_expr(strcmp((char*)(strvdbts[i].get_data()),
|
|
strsv[i].c_str()) == 0);
|
|
}
|
|
strv.clear();
|
|
|
|
if (explicit_txn) {
|
|
dbstl::commit_txn(penv);
|
|
dbstl::begin_txn(0, penv);
|
|
}
|
|
|
|
// Use ordinary way to store strings.
|
|
TCHAR cstr1[32], cstr2[32], cstr3[32];
|
|
strcpy(cstr1, "abc");
|
|
strcpy(cstr2, "defcd");
|
|
strcpy(cstr3, "edggsefcd");
|
|
|
|
typedef db_map<int, TCHAR*, ElementHolder<TCHAR*> > strmap_t;
|
|
strmap_t strmap(dmdb6, penv);
|
|
strmap.clear();
|
|
strmap.insert(make_pair(1, cstr1));
|
|
strmap.insert(make_pair(2, cstr2));
|
|
strmap.insert(make_pair(3, cstr3));
|
|
cout<<"\n strings in strmap:\n";
|
|
for (strmap_t::const_iterator citr = strmap.begin();
|
|
citr != strmap.end(); citr++)
|
|
cout<<(*citr).second<<'\t';
|
|
cout<<strmap[1]<<strmap[2]<<strmap[3];
|
|
TCHAR cstr4[32], cstr5[32], cstr6[32];
|
|
_tcscpy(cstr4, strmap[1]);
|
|
_tcscpy(cstr5, strmap[2]);
|
|
_tcscpy(cstr6, strmap[3]);
|
|
_tprintf(_T("%s, %s, %s"), cstr4, cstr5, cstr6);
|
|
strmap_t::value_type_wrap::second_type vts = strmap[1];
|
|
using_charstr(vts);
|
|
vts._DB_STL_StoreElement();
|
|
_tcscpy(cstr4, _T("hello world"));
|
|
vts = cstr4;
|
|
vts._DB_STL_StoreElement();
|
|
cout<<"\n\nstrmap[1]: "<<strmap[1];
|
|
check_expr(_tcscmp(strmap[1], cstr4) == 0);
|
|
vts[0] = _T('H');// it is wrong to do it this way
|
|
vts._DB_STL_StoreElement();
|
|
check_expr(_tcscmp(strmap[1], _T("Hello world")) == 0);
|
|
TCHAR *strbase = vts._DB_STL_value();
|
|
strbase[6] = _T('W');
|
|
vts._DB_STL_StoreElement();
|
|
check_expr(_tcscmp(strmap[1], _T("Hello World")) == 0);
|
|
strmap.clear();
|
|
|
|
typedef db_map<const char *, const char *,
|
|
ElementHolder<const char *> > cstrpairs_t;
|
|
cstrpairs_t strpairs(dmdb6, penv);
|
|
strpairs["abc"] = "def";
|
|
strpairs["ghi"] = "jkl";
|
|
strpairs["mno"] = "pqrs";
|
|
strpairs["tuv"] = "wxyz";
|
|
cstrpairs_t::const_iterator ciitr;
|
|
cstrpairs_t::iterator iitr;
|
|
for (ciitr = strpairs.begin(), iitr = strpairs.begin();
|
|
iitr != strpairs.end(); ++iitr, ++ciitr) {
|
|
cout<<"\n"<<iitr->first<<"\t"<<iitr->second;
|
|
cout<<"\n"<<ciitr->first<<"\t"<<ciitr->second;
|
|
check_expr(strcmp(ciitr->first, iitr->first) == 0 &&
|
|
strcmp(ciitr->second, iitr->second) == 0);
|
|
}
|
|
|
|
typedef db_map<char *, char *, ElementHolder<char *> > strpairs_t;
|
|
typedef std::map<string, string> sstrpairs_t;
|
|
sstrpairs_t sstrpairs2;
|
|
strpairs_t strpairs2;
|
|
rand_str_dbt randstr;
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
string rdstr, rdstr2;
|
|
randstr(dbt, rdstr);
|
|
randstr(dbt, rdstr2);
|
|
strpairs2[(char *)rdstr.c_str()] = (char *)rdstr2.c_str();
|
|
sstrpairs2[rdstr] = rdstr2;
|
|
}
|
|
strpairs_t::iterator itr;
|
|
strpairs_t::const_iterator citr;
|
|
|
|
for (itr = strpairs2.begin(); itr != strpairs2.end(); ++itr) {
|
|
check_expr(strcmp(strpairs2[itr->first], itr->second) == 0);
|
|
check_expr(string(itr->second) ==
|
|
sstrpairs2[string(itr->first)]);
|
|
strpairs_t::value_type_wrap::second_type&secref = itr->second;
|
|
std::reverse((char *)secref, (char *)secref + strlen(secref));
|
|
secref._DB_STL_StoreElement();
|
|
std::reverse(sstrpairs2[itr->first].begin(),
|
|
sstrpairs2[itr->first].end());
|
|
}
|
|
|
|
check_expr(strpairs2.size() == sstrpairs2.size());
|
|
for (citr = strpairs2.begin(
|
|
ReadModifyWriteOption::no_read_modify_write(),
|
|
true, BulkRetrievalOption::bulk_retrieval());
|
|
citr != strpairs2.end(); ++citr) {
|
|
check_expr(strcmp(strpairs2[citr->first], citr->second) == 0);
|
|
check_expr(string(citr->second) ==
|
|
sstrpairs2[string(citr->first)]);
|
|
}
|
|
|
|
|
|
if (explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
|
|
db_vector<const char *, ElementHolder<const char *> > csvct(10);
|
|
vector<const char *> scsvct(10);
|
|
const char *pconststr = "abc";
|
|
for (i = 0; i < 10; i++) {
|
|
scsvct[i] = pconststr;
|
|
csvct[i] = pconststr;
|
|
csvct[i] = scsvct[i];
|
|
// scsvct[i] = csvct[i]; assignment won't work because scsvct
|
|
// only stores pointer but do not copy the sequence, thus it
|
|
// will refer to an invalid pointer when i changes.
|
|
}
|
|
for (i = 0; i < 10; i++) {
|
|
check_expr(strcmp(csvct[i], scsvct[i]) == 0);
|
|
cout<<endl<<(const char *)(csvct[i]);
|
|
}
|
|
|
|
db_vector<const wchar_t *, ElementHolder<const wchar_t *> > wcsvct(10);
|
|
vector<const wchar_t *> wscsvct(10);
|
|
const wchar_t *pconstwstr = L"abc";
|
|
for (i = 0; i < 10; i++) {
|
|
wscsvct[i] = pconstwstr;
|
|
wcsvct[i] = pconstwstr;
|
|
wcsvct[i] = wscsvct[i];
|
|
// scsvct[i] = csvct[i]; assignment won't work because scsvct
|
|
// only stores pointer but do not copy the sequence, thus it
|
|
// will refer to an invalid pointer when i changes.
|
|
}
|
|
for (i = 0; i < 10; i++) {
|
|
check_expr(wcscmp(wcsvct[i], wscsvct[i]) == 0);
|
|
|
|
}
|
|
|
|
} // char_star_string_storage
|
|
|
|
void StlAdvancedFeaturesExample::arbitray_sequence_storage()
|
|
{
|
|
int i, j;
|
|
|
|
if (explicit_txn)
|
|
dbstl::begin_txn(0, penv);
|
|
// storing arbitary sequence test .
|
|
cout<<endl<<"Arbitary type of sequence storage support.\n";
|
|
RGBB *rgbs[10], *prgb1, *prgb2;
|
|
typedef db_map<int, RGBB *, ElementHolder<RGBB *> > rgbmap_t;
|
|
rgbmap_t rgbsmap(dmdb6, penv);
|
|
|
|
map<int, RGBB *> srgbsmap;
|
|
|
|
DbstlElemTraits<RGBB>::instance()->set_sequence_len_function(rgblen);
|
|
DbstlElemTraits<RGBB>::instance()->set_sequence_copy_function(rgbcpy);
|
|
// populate srgbsmap and rgbsmap
|
|
for (i = 0; i < 10; i++) {
|
|
n = abs(rand()) % 10 + 2;
|
|
rgbs[i] = new RGBB[n];
|
|
memset(&rgbs[i][n - 1], 0, sizeof(RGBB));//make last element 0
|
|
for (j = 0; j < n - 1; j++) {
|
|
rgbs[i][j].r_ = i + 128;
|
|
rgbs[i][j].g_ = 256 - i;
|
|
rgbs[i][j].b_ = 128 - i;
|
|
rgbs[i][j].bright_ = 256 / (i + 1);
|
|
|
|
}
|
|
rgbsmap.insert(make_pair(i, rgbs[i]));
|
|
srgbsmap.insert(make_pair(i, rgbs[i]));
|
|
}
|
|
|
|
// retrieve and assert equal, then modify and store
|
|
for (i = 0; i < 10; i++) {
|
|
rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i];
|
|
prgb1 = rgbelem;
|
|
check_expr(memcmp(prgb1, prgb2 = srgbsmap[i],
|
|
(n = (int)rgblen(srgbsmap[i])) * sizeof(RGBB)) == 0);
|
|
for (j = 0; j < n - 1; j++) {
|
|
prgb1[j].r_ = 256 - prgb1[j].r_;
|
|
prgb1[j].g_ = 256 - prgb1[j].g_;
|
|
prgb1[j].b_ = 256 - prgb1[j].b_;
|
|
prgb2[j].r_ = 256 - prgb2[j].r_;
|
|
prgb2[j].g_ = 256 - prgb2[j].g_;
|
|
prgb2[j].b_ = 256 - prgb2[j].b_;
|
|
}
|
|
rgbelem._DB_STL_StoreElement();
|
|
}
|
|
|
|
// retrieve again and assert equal
|
|
for (i = 0; i < 10; i++) {
|
|
rgbmap_t::value_type_wrap::second_type rgbelem = rgbsmap[i];
|
|
// Can't use rgbsmap[i] here because container::operator[] is
|
|
// an temporary value.;
|
|
prgb1 = rgbelem;
|
|
check_expr(memcmp(prgb1, prgb2 = srgbsmap[i],
|
|
sizeof(RGBB) * rgblen(srgbsmap[i])) == 0);
|
|
}
|
|
|
|
rgbmap_t::iterator rmitr;
|
|
map<int, RGBB *>::iterator srmitr;
|
|
|
|
for (rmitr = rgbsmap.begin();
|
|
rmitr != rgbsmap.end(); ++rmitr) {
|
|
rgbmap_t::value_type_wrap::second_type
|
|
rgbelem2 = (*rmitr).second;
|
|
prgb1 = (*rmitr).second;
|
|
srmitr = srgbsmap.find(rmitr->first);
|
|
rmitr.refresh();
|
|
}
|
|
|
|
for (i = 0; i < 10; i++)
|
|
delete []rgbs[i];
|
|
if (explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
} // arbitray_sequence_storage
|
|
|
|
void StlAdvancedFeaturesExample::bulk_retrieval_read()
|
|
{
|
|
|
|
int i;
|
|
|
|
typedef db_map<int, sms_t> smsmap_t;
|
|
smsmap_t smsmap(dmdb6, penv);
|
|
map<int, sms_t> ssmsmap;
|
|
if (explicit_txn)
|
|
dbstl::begin_txn(0, penv);
|
|
|
|
cout<<"\nBulk retrieval support:\n";
|
|
sms_t smsmsg;
|
|
time_t now;
|
|
smsmap.clear();
|
|
for (i = 0; i < 2008; i++) {
|
|
smsmsg.from = 1000 + i;
|
|
smsmsg.to = 10000 - i;
|
|
smsmsg.sz = sizeof(smsmsg);
|
|
time(&now);
|
|
smsmsg.when = now;
|
|
ssmsmap.insert(make_pair(i, smsmsg));
|
|
smsmap.insert(make_pair(i, smsmsg));
|
|
}
|
|
|
|
// bulk retrieval test.
|
|
map<int, sms_t>::iterator ssmsitr = ssmsmap.begin();
|
|
i = 0;
|
|
const smsmap_t &rosmsmap = smsmap;
|
|
smsmap_t::const_iterator smsitr;
|
|
for (smsitr = rosmsmap.begin(
|
|
BulkRetrievalOption::bulk_retrieval());
|
|
smsitr != smsmap.end(); i++) {
|
|
// The order may be different, so if the two key set are
|
|
// identical, it is right.
|
|
check_expr((ssmsmap.count(smsitr->first) == 1));
|
|
check_expr((smsitr->second == ssmsmap[smsitr->first]));
|
|
if (i % 2)
|
|
smsitr++;
|
|
else
|
|
++smsitr; // Exercise both pre/post increment.
|
|
if (i % 100 == 0)
|
|
smsitr.set_bulk_buffer(
|
|
(u_int32_t)(smsitr.get_bulk_bufsize() * 1.1));
|
|
}
|
|
|
|
smsmap.clear();
|
|
ssmsmap.clear();
|
|
|
|
// Using db_vector. when moving its iterator sequentially to end(),
|
|
// bulk retrieval works, if moving randomly, it dose not function
|
|
// for db_vector iterators. Also, note that we can create a read only
|
|
// iterator when using db_vector<>::iterator rather than
|
|
// db_vector<>::const_iterator.
|
|
db_vector<sms_t> vctsms;
|
|
db_vector<sms_t>::iterator itrv;
|
|
vector<sms_t>::iterator sitrv;
|
|
vector<sms_t> svctsms;
|
|
for (i = 0; i < 2008; i++) {
|
|
smsmsg.from = 1000 + i;
|
|
smsmsg.to = 10000 - i;
|
|
smsmsg.sz = sizeof(smsmsg);
|
|
time(&now);
|
|
smsmsg.when = now;
|
|
vctsms.push_back(smsmsg);
|
|
svctsms.push_back(smsmsg);
|
|
}
|
|
|
|
for (itrv = vctsms.begin(ReadModifyWriteOption::no_read_modify_write(),
|
|
true, BulkRetrievalOption::bulk_retrieval(64 * 1024)),
|
|
sitrv = svctsms.begin(), i = 0; itrv != vctsms.end();
|
|
++itrv, ++sitrv, ++i) {
|
|
check_expr(*itrv == *sitrv);
|
|
if (i % 100 == 0)
|
|
itrv.set_bulk_buffer(
|
|
(u_int32_t)(itrv.get_bulk_bufsize() * 1.1));
|
|
}
|
|
|
|
if (explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
|
|
|
|
} //bulk_retrieval_read
|
|
|
|
void StlAdvancedFeaturesExample::primitive()
|
|
{
|
|
|
|
int i;
|
|
|
|
if ( explicit_txn)
|
|
dbstl::begin_txn(0, penv);
|
|
|
|
|
|
db_vector<int, ElementHolder<int> > ivi(dbprim, penv);
|
|
vector<int> spvi4;
|
|
fill(ivi, spvi4);
|
|
check_expr(is_equal(ivi, spvi4));
|
|
ivi.clear(false);
|
|
|
|
db_vector<int, ElementHolder<int> > ivi2(dbprim, penv);
|
|
vector<int> spvi5;
|
|
fill(ivi2, spvi5);
|
|
check_expr(is_equal(ivi2, spvi5));
|
|
size_t vsz = ivi2.size();
|
|
for (i = 0; i < (int)vsz - 1; i++) {
|
|
ivi2[i] += 3;
|
|
ivi2[i]--;
|
|
ivi2[i] <<= 2;
|
|
ivi2[i] = (~ivi2[i] | ivi2[i] & ivi2[i + 1] ^
|
|
(2 * (-ivi2[i + 1]) + ivi2[i]) * 3) /
|
|
(ivi2[i] * ivi2[i + 1] + 1);
|
|
|
|
spvi5[i] += 3;
|
|
spvi5[i]--;
|
|
spvi5[i] <<= 2;
|
|
spvi5[i] = (~spvi5[i] | spvi5[i] & spvi5[i + 1] ^
|
|
(2 * (-spvi5[i + 1]) + spvi5[i]) * 3) /
|
|
(spvi5[i] * spvi5[i + 1] + 1);
|
|
}
|
|
check_expr(is_equal(ivi2, spvi5));
|
|
ivi2.clear(false);
|
|
|
|
typedef db_vector<double, ElementHolder<double> > dbl_vct_t;
|
|
dbl_vct_t dvi(dbprim, penv);
|
|
vector<double> dsvi;
|
|
for (i = 0; i < 10; i++) {
|
|
dvi.push_back(i * 3.14);
|
|
dsvi.push_back(i * 3.14);
|
|
}
|
|
check_expr(is_equal(dvi, dsvi));
|
|
|
|
dbl_vct_t::iterator ditr;
|
|
vector<double>::iterator sditr;
|
|
for (ditr = dvi.begin(), sditr = dsvi.begin();
|
|
ditr != dvi.end(); ++ditr, ++sditr){
|
|
*ditr *= 2;
|
|
*sditr *= 2;
|
|
}
|
|
|
|
check_expr(is_equal(dvi, dsvi));
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
dvi[i] /= (-dvi[i] / 3 + 2 * dvi[i + 1]) / (1 + dvi[i]) + 1;
|
|
dsvi[i] /= (-dsvi[i] / 3 + 2 * dsvi[i + 1]) / (1 + dsvi[i]) + 1;
|
|
}
|
|
|
|
cout<<"\ndsvi after math operations: \n";
|
|
for (i = 0; i <= 9; i++)
|
|
cout<<dsvi[i]<<" ";
|
|
for (i = 0; i < 10; i++) {
|
|
cout<<i<<"\t";
|
|
check_expr((int)(dvi[i] * 100000) == (int)(dsvi[i] * 100000));
|
|
}
|
|
|
|
if ( explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
} // primitive
|
|
|
|
void StlAdvancedFeaturesExample::queue_stack()
|
|
{
|
|
int i;
|
|
|
|
if ( explicit_txn)
|
|
dbstl::begin_txn(0, penv);
|
|
// test whether db_vector works with std::queue,
|
|
// std::priority_queue and std::stack
|
|
cout<<"\ndb_vector working with std::queue\n";
|
|
|
|
// std::queue test
|
|
intvec_t quev(quedb, penv);
|
|
quev.clear();
|
|
std::queue<ptint, intvec_t> intq(quev);
|
|
std::queue<ptint> sintq;
|
|
check_expr(intq.empty());
|
|
check_expr(intq.size() == 0);
|
|
for (i = 0; i < 100; i++) {
|
|
intq.push(ptint(i));
|
|
sintq.push(i);
|
|
check_expr(intq.front() == 0);
|
|
check_expr(intq.back() == i);
|
|
}
|
|
check_expr(intq.size() == 100);
|
|
for (i = 0; i < 100; i++) {
|
|
check_expr(intq.front() == i);
|
|
check_expr(intq.back() == 99);
|
|
check_expr(intq.front() == sintq.front());
|
|
check_expr(sintq.back() == intq.back());
|
|
sintq.pop();
|
|
intq.pop();
|
|
}
|
|
check_expr(intq.size() == 0);
|
|
check_expr(intq.empty());
|
|
quev.clear();
|
|
|
|
// std::priority_queue test
|
|
cout<<"\ndb_vector working with std::priority_queue\n";
|
|
|
|
std::vector<ptint> squev;
|
|
intvec_t pquev(pquedb, penv);
|
|
pquev.clear();
|
|
std::priority_queue<ptint, intvec_t, ptintless_ft>
|
|
intpq(ptintless, pquev);
|
|
std::priority_queue<ptint, vector<ptint>, ptintless_ft>
|
|
sintpq(ptintless, squev);
|
|
|
|
check_expr(intpq.empty());
|
|
check_expr(intpq.size() == 0);
|
|
ptint tmppq, tmppq1;
|
|
set<ptint> ptintset;
|
|
for (i = 0; i < 100; i++) {
|
|
for (;;) {// avoid duplicate
|
|
tmppq = rand();
|
|
if (ptintset.count(tmppq) == 0) {
|
|
intpq.push(tmppq);
|
|
sintpq.push(tmppq);
|
|
ptintset.insert(tmppq);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
check_expr(intpq.empty() == false);
|
|
check_expr(intpq.size() == 100);
|
|
for (i = 0; i < 100; i++) {
|
|
tmppq = intpq.top();
|
|
tmppq1 = sintpq.top();
|
|
if (i == 98 && tmppq != tmppq1) {
|
|
tmppq = intpq.top();
|
|
}
|
|
if (i < 98)
|
|
check_expr(tmppq == tmppq1);
|
|
if (i == 97)
|
|
intpq.pop();
|
|
else
|
|
intpq.pop();
|
|
sintpq.pop();
|
|
}
|
|
check_expr(intpq.empty());
|
|
check_expr(intpq.size() == 0);
|
|
|
|
|
|
// std::stack test
|
|
cout<<"\ndb_vector working with std::stack\n";
|
|
std::stack<ptint, intvec_t> intstk(quev);
|
|
std::stack<ptint> sintstk;
|
|
check_expr(intstk.size() == 0);
|
|
check_expr(intstk.empty());
|
|
for (i = 0; i < 100; i++) {
|
|
intstk.push(ptint(i));
|
|
sintstk.push(ptint(i));
|
|
check_expr(intstk.top() == i);
|
|
check_expr(intstk.size() == (size_t)i + 1);
|
|
}
|
|
|
|
for (i = 99; i >= 0; i--) {
|
|
check_expr(intstk.top() == ptint(i));
|
|
check_expr(intstk.top() == sintstk.top());
|
|
sintstk.pop();
|
|
intstk.pop();
|
|
check_expr(intstk.size() == (size_t)i);
|
|
}
|
|
check_expr(intstk.size() == 0);
|
|
check_expr(intstk.empty());
|
|
|
|
// Vector with no handles specified.
|
|
ptint_vector simple_vct(10);
|
|
vector<ptint> ssvct(10);
|
|
for (i = 0; i < 10; i++) {
|
|
simple_vct[i] = ptint(i);
|
|
ssvct[i] = ptint(i);
|
|
}
|
|
check_expr(is_equal(simple_vct, ssvct));
|
|
|
|
if ( explicit_txn)
|
|
dbstl::commit_txn(penv);
|
|
|
|
return;
|
|
} // queue_stack
|
|
|
|
DbEnv *g_env;
|
|
int g_test_start_txn;
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int c, ret;
|
|
char *envhome = NULL, *mode = NULL;
|
|
int flags = DB_THREAD, setflags = 0, explicit_txn = 0;
|
|
int test_autocommit = 1, totalinsert = 100, verbose = 0;
|
|
DBTYPE dbtype = DB_BTREE;
|
|
int shortest = 50, longest = 200;
|
|
u_int32_t cachesize = 8 * 1024 * 1024;
|
|
DbEnv *penv = NULL;
|
|
|
|
TestParam *ptp = new TestParam;
|
|
|
|
while ((c = getopt(argc, argv, "T:c:hH:k:l:m:n:r:s:t:v")) != EOF) {
|
|
switch (c) {
|
|
case 'T':
|
|
totalinsert = atoi(optarg);
|
|
break;
|
|
case 'c':
|
|
cachesize = atoi(optarg);
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
return 0;
|
|
break;
|
|
case 'H':
|
|
envhome = strdup(optarg);
|
|
break;
|
|
case 'k':
|
|
shortest = atoi(optarg);
|
|
break;
|
|
case 'l':
|
|
longest = atoi(optarg);
|
|
break;
|
|
case 'm':
|
|
mode = optarg;
|
|
break;
|
|
case 's': // db type for associative containers
|
|
if (*optarg == 'h') // hash db type
|
|
dbtype = DB_HASH;
|
|
else if (*optarg == 'b')
|
|
dbtype = DB_BTREE;
|
|
else
|
|
usage();
|
|
break;
|
|
case 't':
|
|
explicit_txn = 1;
|
|
if (*optarg == 'a')
|
|
setflags = DB_AUTO_COMMIT;
|
|
else if (*optarg == 'e') // explicit txn
|
|
test_autocommit = 0;
|
|
else
|
|
usage();
|
|
break;
|
|
case 'v':
|
|
verbose = 1;
|
|
break;
|
|
default:
|
|
usage();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mode == NULL)
|
|
flags |= 0;
|
|
else if (*mode == 'c') //cds
|
|
flags |= DB_INIT_CDB;
|
|
else if (*mode == 't')
|
|
flags |= DB_INIT_TXN | DB_RECOVER
|
|
| DB_INIT_LOG | DB_INIT_LOCK;
|
|
else
|
|
flags |= 0;
|
|
|
|
ptp->explicit_txn = explicit_txn;
|
|
ptp->flags = flags;
|
|
ptp->dbtype = dbtype;
|
|
ptp->setflags = setflags;
|
|
ptp->test_autocommit = test_autocommit;
|
|
ptp->dboflags = DB_THREAD;
|
|
|
|
// Call this method before any use of dbstl.
|
|
dbstl_startup();
|
|
penv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
|
|
BDBOP(penv->set_flags(setflags, 1), ret);
|
|
BDBOP(penv->set_cachesize(0, cachesize, 1), ret);
|
|
|
|
// Methods of containers returning a reference costs
|
|
// locker/object/lock slots.
|
|
penv->set_lk_max_lockers(10000);
|
|
penv->set_lk_max_objects(10000);
|
|
penv->set_lk_max_locks(10000);
|
|
|
|
penv->set_flags(DB_TXN_NOSYNC, 1);
|
|
|
|
BDBOP(penv->open(envhome,
|
|
flags | DB_CREATE | DB_INIT_MPOOL, 0777), ret);
|
|
register_db_env(penv);
|
|
ptp->dbenv = penv;
|
|
g_env = penv;
|
|
g_test_start_txn = test_autocommit * explicit_txn;
|
|
|
|
// Create the example and run.
|
|
StlAdvancedFeaturesExample example(ptp);
|
|
example.run();
|
|
|
|
// Clean up and exit.
|
|
delete ptp;
|
|
dbstl_exit();// Call this method before the process exits.
|
|
if (penv)
|
|
delete penv;
|
|
}
|
|
|
|
void usage()
|
|
{
|
|
cout<<
|
|
"\nUsage: StlAdvancedFeaturesExample\n\
|
|
[-c number cache size]\n\
|
|
[-h print this help message then exit]\n\
|
|
[-H dir Specify dir as environment home]\n\
|
|
[-k number shortest string inserted]\n\
|
|
[-l number longest string inserted]\n\
|
|
[-m ds/cds/tds use ds/cds/tds product]\n\
|
|
[-s b/h use btree/hash type of DB for assocative \
|
|
containers] \n\
|
|
[-t a/e for tds, use autocommit/explicit transaction in \
|
|
the test] \n\
|
|
[-v verbose mode, output more info in multithread \
|
|
test]\n\
|
|
";
|
|
}
|
|
|
|
void using_charstr(TCHAR*str)
|
|
{
|
|
cout<<_T("using str read only with non-const parameter type:")<<str;
|
|
str[0] = _T('U');
|
|
str[1] = _T('R');
|
|
}
|
|
|
|
int get_dest_secdb_callback(Db * /* secondary */, const Dbt * /* key */,
|
|
const Dbt *data, Dbt *result)
|
|
{
|
|
SMSMsg *p = (SMSMsg*)data->get_data();
|
|
|
|
result->set_data(&(p->to));
|
|
result->set_size(sizeof(p->to));
|
|
return 0;
|
|
}
|
|
|
|
void SMSMsgRestore(SMSMsg2& dest, const void *srcdata)
|
|
{
|
|
char *p = dest.msg;
|
|
|
|
memcpy(&dest, srcdata, sizeof(dest));
|
|
|
|
dest.msg = (char *)DbstlReAlloc(p, dest.szmsg);
|
|
strcpy(dest.msg, (char*)srcdata + sizeof(dest));
|
|
}
|
|
|
|
u_int32_t SMSMsgSize(const SMSMsg2& elem)
|
|
{
|
|
return (u_int32_t)(sizeof(elem) + strlen(elem.msg) + 1);
|
|
}
|
|
|
|
void SMSMsgCopy(void *dest, const SMSMsg2&elem)
|
|
{
|
|
memcpy(dest, &elem, sizeof(elem));
|
|
strcpy((char*)dest + sizeof(elem), elem.msg);
|
|
}
|
|
|
|
u_int32_t rgblen(const RGBB *seq)
|
|
{
|
|
size_t s = 0;
|
|
|
|
const RGBB *p = seq, rgb0;
|
|
for (s = 0, p = seq; memcmp(p, &rgb0, sizeof(rgb0)) != 0; p++, s++);
|
|
// this size includes the all-0 last element used like '\0'
|
|
// for char* strings
|
|
return (u_int32_t)(s + 1);
|
|
}
|
|
|
|
// The seqs sequence of RGBB objects may not reside in a consecutive chunk of
|
|
// memory but the seqd points to a consecutive chunk of mem large enough to
|
|
// hold all objects from seqs.
|
|
void rgbcpy(RGBB *seqd, const RGBB *seqs, size_t num)
|
|
{
|
|
const RGBB *p = seqs;
|
|
RGBB rgb0;
|
|
RGBB *q = seqd;
|
|
|
|
memset((void *)&rgb0, 0, sizeof(rgb0));
|
|
for (p = seqs, q = seqd; memcmp(p, &rgb0, sizeof(rgb0)) != 0 &&
|
|
num > 0; num--, p++, q++)
|
|
memcpy((void *)q, p, sizeof(RGBB));
|
|
memcpy((void *)q, p, sizeof(RGBB));// append trailing end token.
|
|
}
|