summaryrefslogtreecommitdiff
path: root/db-4.8.30/test_stl/base
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
committerJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
commit54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch)
tree18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/test_stl/base
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test_stl/base')
-rw-r--r--db-4.8.30/test_stl/base/ptype.h260
-rw-r--r--db-4.8.30/test_stl/base/test.h470
-rw-r--r--db-4.8.30/test_stl/base/test_assoc.h2470
-rw-r--r--db-4.8.30/test_stl/base/test_dbstl.cpp313
-rw-r--r--db-4.8.30/test_stl/base/test_mt.h914
-rw-r--r--db-4.8.30/test_stl/base/test_util.cpp280
-rw-r--r--db-4.8.30/test_stl/base/test_util.h605
-rw-r--r--db-4.8.30/test_stl/base/test_vector.h1338
8 files changed, 6650 insertions, 0 deletions
diff --git a/db-4.8.30/test_stl/base/ptype.h b/db-4.8.30/test_stl/base/ptype.h
new file mode 100644
index 0000000..574f7b9
--- /dev/null
+++ b/db-4.8.30/test_stl/base/ptype.h
@@ -0,0 +1,260 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#ifndef _DB_STL_PTYPE_H
+#define _DB_STL_PTYPE_H
+
+#include "dbstl_common.h"
+#include "dbstl_element_ref.h"
+#include <iostream>
+
+using std::istream;
+using std::ostream;
+using namespace dbstl;
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+//
+// ptype class template definition
+//
+// ptype<> is a primitive types wrapper, must use this wrapper to
+// store/retrieve primitive types to/from db via db stl interface
+//
+template <Typename T>
+class ptype
+{
+public:
+ T v;
+ ptype(){v = 0;}
+ ptype(T vv){v = vv;}
+ typedef ptype<T> tptype;
+ typedef db_vector_iterator<tptype> dvit;
+
+ operator T()
+ {
+ return v;
+ }
+
+ ptype(const ElementRef<ptype<T> >&rval)
+ {
+ if ( rval._DB_STL_GetData(*this) != INVALID_KEY_DATA) {
+
+ } else {
+ throw new InvalidDbtException();
+ }
+ }
+
+ ptype(const ptype<T>&p2)
+ {
+ v = p2.v;
+ }
+
+ template <Typename T2>
+ ptype(const ptype<T2>&p2)
+ {
+ v = p2.v;
+ }
+ template <Typename T2>
+ const ptype<T>& operator=(const ptype<T2>&p2)
+ {
+ v = p2.v;
+ return *this;
+ }
+ template <Typename T2>
+ const ptype<T> operator +(const ptype<T2> &p2) const
+ {
+ return ptype<T>(v + p2.v );
+ }
+ template <Typename T2>
+ const ptype<T> operator -(const ptype<T2> &p2) const
+ {
+ return ptype<T>(v - p2.v );
+ }
+ template <Typename T2>
+ const ptype<T> operator *(const ptype<T2> &p2) const
+ {
+ return ptype<T>(v * p2.v );
+ }
+ template <Typename T2>
+ const ptype<T> operator /(const ptype<T2> &p2) const
+ {
+ return ptype<T>(v / p2.v );
+ }
+ template <Typename T2>
+ const ptype<T> operator %(const ptype<T2> &p2) const
+ {
+ return ptype<T>(v % p2.v );
+ }
+
+ template <Typename T2>
+ const ptype<T>& operator +=(const ptype<T2> &p2) const
+ {
+ v += p2.v;
+ return *this;
+ }
+
+ template <Typename T2>
+ const ptype<T>& operator -=(const ptype<T2> &p2) const
+ {
+ v -= p2.v;
+ return *this;
+ }
+ template <Typename T2>
+ const ptype<T>& operator *=(const ptype<T2> &p2) const
+ {
+ v *= p2.v;
+ return *this;
+ }
+ template <Typename T2>
+ const ptype<T>& operator /=(const ptype<T2> &p2) const
+ {
+ v /= p2.v;
+ return *this;
+ }
+ template <Typename T2>
+ const ptype<T>& operator %=(const ptype<T2> &p2) const
+ {
+ v %= p2.v;
+ return *this;
+ }
+
+ template <Typename T2>
+ bool operator==(const ptype<T2>&p2) const
+ {
+ return v == p2.v;
+ }
+ template <Typename T2>
+ bool operator!=(const ptype<T2>&p2)const
+ {
+ return v != p2.v;
+ }
+
+ template <Typename T2>
+ bool operator<(const ptype<T2>&p2) const
+ {
+ return v < p2.v;
+ }
+
+ template <Typename T2>
+ bool operator>(const ptype<T2>&p2) const
+ {
+ return v > p2.v;
+ }
+
+ template <Typename T2>
+ bool operator<=(const ptype<T2>&p2) const
+ {
+ return v <= p2.v;
+ }
+ template <Typename T2>
+ bool operator>=(const ptype<T2>&p2) const
+ {
+ return v >= p2.v;
+ }
+
+ const ptype<T>& operator=(const ptype<T>&p2)
+ {
+ v = p2.v;
+ return p2;
+ }
+
+ bool operator>(const ptype<T>&p2) const
+ {
+ return v > p2.v;
+ }
+ bool operator<(const ptype<T>&p2) const
+ {
+ return v < p2.v;
+ }
+
+ bool operator>=(const ptype<T>&p2) const
+ {
+ return v >= p2.v;
+ }
+ bool operator<=(const ptype<T>&p2) const
+ {
+ return v <= p2.v;
+ }
+ const ptype<T> operator-() const
+ {
+ return ptype<T>(-v);
+ }
+ // althought the definitionos of following arithmetic operators are quite
+ // alike, we can't define them using macros, seems macro's parameter can only
+ // be symbols or literals, not operators
+ const ptype<T> operator +(const ptype<T> &p2) const
+ {
+ return ptype<T>(v + p2.v );
+ }
+ const ptype<T> operator -(const ptype<T> &p2) const
+ {
+ return ptype<T>(v - p2.v );
+ }
+ const ptype<T> operator *(const ptype<T> &p2) const
+ {
+ return ptype<T>(v * p2.v );
+ }
+ const ptype<T> operator /(const ptype<T> &p2) const
+ {
+ return ptype<T>(v / p2.v );
+ }
+ const ptype<T> operator %(const ptype<T> &p2) const
+ {
+ return ptype<T>(v % p2.v );
+ }
+ const ptype<T>& operator %=(const ptype<T> &p2) const
+ {
+ v %= p2.v;
+ return *this;
+ }
+
+ const ptype<T>& operator +=(const ptype<T> &p2) const
+ {
+ v += p2.v;
+ return *this;
+ }
+ const ptype<T>& operator -=(const ptype<T> &p2) const
+ {
+ v -= p2.v;
+ return *this;
+ }
+ const ptype<T>& operator /=(const ptype<T> &p2) const
+ {
+ v /= p2.v;
+ return *this;
+ }
+ const ptype<T>& operator *=(const ptype<T> &p2) const
+ {
+ v *= p2.v;
+ return *this;
+ }
+}; // ptype
+
+// the following two functions help io ptype objs to/from any streams
+template<Typename _CharT, Typename _Traits, Typename T>
+basic_istream<_CharT,_Traits>&
+operator>>( basic_istream<_CharT,_Traits> & in, ptype<T>&p)
+{
+ in>>p.v;
+ return in;
+}
+
+template<Typename _CharT, Typename _Traits, Typename T>
+basic_ostream<_CharT,_Traits>&
+operator<<( basic_ostream<_CharT,_Traits> & out, const ptype<T>&p)
+{
+ out<<p.v;
+ return out;
+}
+
+template <Typename T>
+T operator * (T t, const ptype<T> &pt)
+{
+ return t * pt.v;
+}
+
+#endif // !_DB_STL_PTYPE_H
diff --git a/db-4.8.30/test_stl/base/test.h b/db-4.8.30/test_stl/base/test.h
new file mode 100644
index 0000000..f5ad545
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test.h
@@ -0,0 +1,470 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#ifndef _DB_STL_TEST_H__
+#define _DB_STL_TEST_H__
+
+#include <time.h>
+
+#include <utility>
+#include <functional>
+#include <algorithm>
+#include <iostream>
+#include <vector>
+#include <list>
+#include <queue>
+#include <stack>
+#include <fstream>
+#include <map>
+#include <set>
+#include <string>
+
+#include "db_config.h"
+#include "db_int.h"
+
+#define DB_STL_HAVE_DB_TIMESPEC 1
+#include "dbstl_map.h"
+#include "dbstl_set.h"
+#include "dbstl_vector.h"
+
+#include "ptype.h"
+
+using namespace std;
+using namespace dbstl;
+
+/////////////////////////////////////////////////////////////////////////
+///////////////////////// Macro and typedef definitions ///////////
+
+#define check_expr(expression) do { \
+ if (!(expression)) { \
+ FailedAssertionException ex(__FILE__, __LINE__, #expression);\
+ throw ex; } } while (0)
+
+#define TEST_PRIMITIVE
+#ifndef TEST_PRIMITIVE
+typedef ptype<int> ptint;
+typedef db_vector<ptint> intvec_t;
+typedef db_vector<ptint> ptint_vector;
+typedef db_map<ptint, ptint> dm_int_t;
+typedef db_multimap<ptint, ptint> dmm_int_t;
+typedef db_set<ptint> dms_int_t;
+typedef db_multiset<ptint> dmms_int_t;
+#define TOINT
+#else
+#define ptint int
+#define TOINT (int)
+typedef db_vector<ptint, ElementHolder<ptint> > intvec_t;
+typedef db_vector<ptint, ElementHolder<ptint> > ptint_vector;
+typedef db_map<ptint, ptint, ElementHolder<ptint> > dm_int_t;
+typedef db_multimap<ptint, ptint, ElementHolder<ptint> > dmm_int_t;
+typedef db_set<ptint, ElementHolder<ptint> > dms_int_t;
+typedef db_multiset<ptint, ElementHolder<ptint> > dmms_int_t;
+#endif
+
+#define DELDB(pdb) if (pdb){delete pdb; pdb = NULL;}
+#define print_mm(dmm1, dmmi) \
+for (dmmi = dmm1.begin(); dmmi != dmm1.end(); dmmi++) \
+ cout<<dmmi->first<<'\t'<<dmmi->second;
+
+// Portable thread functions, supporting Win32 and pthread libraries
+// These functions are used by the multi-threaded test.
+#if defined(DB_WIN32) || defined(WIN32)
+
+extern "C" {
+extern int getopt(int, char * const *, const char *);
+extern char *optarg;
+extern int optind;
+}
+
+typedef HANDLE os_pid_t;
+typedef HANDLE os_thread_t;
+
+#define os_thread_create(thrp, attr, func, arg) \
+ (((*(thrp) = CreateThread(NULL, 0, \
+ (LPTHREAD_START_ROUTINE)(func), (arg), 0, NULL)) == NULL) ? -1 : 0)
+#define os_thread_join(thr, statusp) \
+ ((WaitForSingleObject((thr), INFINITE) == WAIT_OBJECT_0) && \
+ GetExitCodeThread((thr), (LPDWORD)(statusp)) ? 0 : -1)
+#define os_thread_self() GetCurrentThreadId()
+#else /* !DB_WIN32 */
+
+#include <sys/wait.h>
+#include <pthread.h>
+
+typedef pid_t os_pid_t;
+typedef pthread_t os_thread_t;
+
+#define os_thread_create(thrp, attr, func, arg) \
+ pthread_create((thrp), (attr), (func), (arg))
+#define os_thread_join(thr, statusp) pthread_join((thr), (statusp))
+#define os_thread_self() pthread_self()
+#endif /* !DB_WIN32 */
+
+////////////////////////////////////////////////////////////////////////////
+///////////////////// Global variable declarations ////////////////////////
+/*extern DbEnv *penv;
+extern Db *db, *db2, *db3, *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1,
+ *dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv;
+*/
+extern int g_StopInsert;
+extern ofstream fout;
+extern size_t g_count[256];
+extern char *optarg;
+extern int g_test_start_txn;
+extern DbEnv *g_env;
+extern int optind;
+///////////////////////////////////////////////////////////////////////
+//////////////////////// Function Declarations ////////////////////
+// XXX!!! Function templates can't be declared here otherwise the declarations
+// here will be deemed as the definition, so at link time these symbols are
+// not resolved. So like class templates, function templates can't be separated
+// as declarations and definitions, only definitions and only be built into one
+// object file otherwise there will be "multiple symbol definitions". OTOH, compilers
+// can avoid the multiple definitions if we are building a class template instantiation
+// in multiple object files, so class tempaltes are recommended to use rather than
+// function templates. Only use function templates if it is a simple one and used
+// only in one code file.
+//
+size_t g_sum(size_t s, size_t e);
+bool is_odd(ptint s);
+ptint addup(const ptint&i, const ptint&j);
+ptint randint();
+int randpos(int p);
+bool is2digits(ptint i);
+int rmdir_rcsv(const char *dir, bool keep_this_dir);
+bool strlt(const string&, const string&);
+bool strlt0(const char *s1, const char *s2);
+bool streq0(const char *s1, const char *s2);
+bool streq(const string&, const string&);
+
+int get_dest_secdb_callback(Db *secondary, const Dbt *key,
+ const Dbt *data, Dbt *result);
+void copy_array(TCHAR**arr, TCHAR***dest);
+void using_charstr(TCHAR*str);
+void usage();
+int test_assoc(void* param1);
+int test_vector(void* param1);
+
+class RGBB;
+class SMSMsg2;
+void SMSMsgRestore(SMSMsg2& dest, const void *srcdata);
+u_int32_t SMSMsgSize(const SMSMsg2& elem);
+void SMSMsgCopy(void *dest, const SMSMsg2&elem);
+typedef bool (*ptintless_ft)(const ptint& a, const ptint& b);
+bool ptintless(const ptint& a, const ptint& b);
+u_int32_t rgblen(const RGBB * seq);
+void rgbcpy(RGBB *seq, const RGBB *, size_t);
+
+
+/////////////////////////////////////////////////////////////////////////////////
+////////////////////////// Utility class definitions ///////////////////////////
+
+class BaseMsg
+{
+public:
+ time_t when;
+ int to;
+ int from;
+
+ BaseMsg()
+ {
+ to = from = 0;
+ when = 0;
+ }
+
+ BaseMsg(const BaseMsg& msg)
+ {
+ to = msg.to;
+ from = msg.from;
+ when = msg.when;
+ }
+
+ bool operator==(const BaseMsg& msg2) const
+ {
+ return when == msg2.when && to == msg2.to && from == msg2.from;
+ }
+
+ bool operator<(const BaseMsg& msg2) const
+ {
+ return to < msg2.to;
+ }
+};
+
+// used to test arbitary obj storage(not in one chunk)
+class SMSMsg2 : public BaseMsg
+{
+public:
+ typedef SMSMsg2 self;
+ SMSMsg2(time_t tm, const char *msgp, int t)
+ {
+ memset(this, 0, sizeof(*this));
+ when = tm;
+ szmsg = strlen(msgp) + 1;
+ msg = (char *)DbstlMalloc(szmsg);
+ strncpy(msg, msgp, szmsg);
+ to = t;
+
+ mysize = sizeof(*this); //+ szmsg;
+ }
+
+ SMSMsg2()
+ {
+ memset(this, 0, sizeof(SMSMsg2));
+ }
+
+ SMSMsg2(const self& obj) : BaseMsg(obj)
+ {
+ mysize = obj.mysize;
+ szmsg = obj.szmsg;
+ if (szmsg > 0 && obj.msg != NULL) {
+ msg = (char *)DbstlMalloc(szmsg);
+ strncpy(msg, obj.msg, szmsg);
+ } else
+ msg = NULL;
+ }
+
+ ~SMSMsg2()
+ {
+ if (msg)
+ free(msg);
+ }
+
+ const self& operator = (const self &obj)
+ {
+
+ this->from = obj.from;
+ to = obj.to;
+ when = obj.when;
+ mysize = obj.mysize;
+ szmsg = obj.szmsg;
+ if (szmsg > 0 && obj.msg != NULL) {
+ msg = (char *)DbstlReAlloc(msg, szmsg);
+ strncpy(msg, obj.msg, szmsg);
+ }
+ return obj;
+ }
+
+ bool operator == (const self&obj) const
+ {
+ return BaseMsg::operator==(obj) && strcmp(obj.msg, msg) == 0;
+ }
+
+ const static size_t BUFLEN = 256;
+ size_t mysize;
+ size_t szmsg;
+ char *msg;
+
+};//SMSMsg2
+
+// SMS message class
+class SMSMsg : public BaseMsg
+{
+
+
+public:
+
+ size_t mysize;
+ size_t szmsg;
+ char msg[1];
+ static SMSMsg* make_sms_msg(time_t t, const char*msg, int dest)
+ {
+ size_t mlen = 0, totalsz = 0;
+
+ SMSMsg *p = (SMSMsg *)DbstlMalloc(totalsz = (sizeof(SMSMsg) + (mlen = strlen(msg) + 4)));
+ memset(p, 0, totalsz);
+ // adding sizeof(p->to) to avoid memory alignment issues
+ p->mysize = sizeof(SMSMsg) + mlen;
+ p->when = t;
+ p->szmsg = mlen - 3;
+ p->to = dest;
+ p->from = 0;
+ strcpy(&(p->msg[0]), msg);
+
+ return p;
+ }
+
+ SMSMsg()
+ {
+
+ }
+protected:
+ SMSMsg(time_t t, const char*msg1, int dest)
+ {
+ size_t mlen = 0;
+
+ when = t;
+ szmsg = strlen(msg1) + 1;
+ mlen = strlen(msg1);
+ strncpy((char*)&(this->msg[0]), msg1, mlen);
+ *(int*)(((char*)&(this->msg[0])) + mlen + 1) = dest;
+ }
+
+};// SMSMsg
+
+class RGBB
+{
+public:
+ typedef unsigned char color_t;
+
+ color_t r_, g_, b_, bright_;
+
+ RGBB()
+ {
+ memset(this, 0, sizeof(RGBB));// complete 0 means invalid
+ }
+
+ RGBB(color_t r, color_t g, color_t b, color_t brightness)
+ {
+ r_ = r;
+ g_ = g;
+ b_ = b;
+ bright_ = brightness;
+ }
+
+};// RGBB
+
+template <Typename T>
+class separator
+{
+public:
+ T mid;
+ bool operator()(const T& ele)
+ {
+ return ele < mid;
+ }
+};
+
+
+class square
+{
+public:
+ void operator()(ptint s)
+ {
+ cout<<s*s<<'\t';
+ }
+};
+
+
+class rand_str_dbt
+{
+public:
+ static const size_t BUFLEN = 2048;
+ static bool init;
+ static char buf[BUFLEN];
+
+ rand_str_dbt()
+ {
+ int len = BUFLEN, i;
+
+ if (!init) {
+ init = true;
+
+ for (i = 0; i < len - 1; i++) {
+ buf[i] = 'a' + rand() % 26;
+ }
+ buf[i] = '\0';
+ }
+ }
+ // dbt is of DB_DBT_USERMEM, mem allocated by DbstlMalloc
+ void operator()(Dbt&dbt, string&str, size_t shortest = 30, size_t longest = 150)
+ {
+ int rd = rand();
+
+ if (rd < 0)
+ rd = -rd;
+ str.clear();
+
+ check_expr(shortest > 0 && longest < BUFLEN);
+ check_expr(dbt.get_flags() & DB_DBT_USERMEM);// USER PROVIDE MEM
+ size_t len = (u_int32_t)(rd % longest);
+ if (len < shortest)
+ len = shortest;
+ else if (len >= BUFLEN)
+ len = BUFLEN - 1;
+ // start must be less than BUFLEN - len, otherwise we have no
+ // len bytes to offer
+ size_t start = rand() % (BUFLEN - len);
+
+ char c = buf[start + len];
+
+ buf[start + len] = '\0';
+ str = buf + start;
+ if (dbt.get_ulen() < (len + 1)) {
+ free(dbt.get_data());
+ dbt.set_data(DbstlMalloc(len + 1));
+ check_expr(dbt.get_data() != NULL);
+ }
+ memcpy(dbt.get_data(), (void*)(buf + start), len + 1);
+ dbt.set_size(u_int32_t(len + 1));// store the '\0' at the end
+ buf[start + len] = c;
+ }
+}; // rand_str_dbt
+
+class rand_str_dbt;
+struct TestParam{
+ int flags, setflags, TEST_AUTOCOMMIT, dboflags, EXPLICIT_TXN;
+ DBTYPE dbtype;
+ DbEnv *dbenv;
+};
+
+class test_block
+{
+private:
+ db_timespec tp;
+public:
+ string blkname;
+
+ void begin(const char* name)
+ {
+
+ blkname = name;
+ cout<<endl<<"============= start of test "<<
+ name<<" ==============";
+ __os_gettime(NULL, &tp, 1);
+ }
+ void end()
+ {
+ db_timespec tp2;
+ __os_gettime(NULL, &tp2, 1);
+
+ cout<<"\n============ end of test "<<blkname<<" , time spent: "
+ <<tp2.tv_sec - tp.tv_sec + (tp2.tv_nsec -
+ tp.tv_nsec) / 1000000000.0<<" secs =============";
+ }
+};
+
+// a mobile phone SMS structure for test. will add more members in future
+class sms_t
+{
+public:
+ size_t sz;
+ time_t when;
+ int from;
+ int to;
+ char msg[512];
+
+ const sms_t& operator=(const sms_t&me)
+ {
+ memcpy(this, &me, sizeof(*this));
+ return me;
+ }
+
+ bool operator==(const sms_t& me) const
+ {
+ return memcmp(this, &me, sizeof(me)) == 0;
+ }
+ bool operator!=(const sms_t& me)
+ {
+ return memcmp(this, &me, sizeof(me)) != 0;
+ }
+};
+
+enum wt_job {wt_read, wt_insert, wt_update, wt_delete};
+enum ContainerType {ct_vector, ct_map, ct_multimap, ct_set, ct_multiset, ct_none};
+
+#endif // ! _DB_STL_TEST_H__
diff --git a/db-4.8.30/test_stl/base/test_assoc.h b/db-4.8.30/test_stl/base/test_assoc.h
new file mode 100644
index 0000000..a4bca87
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_assoc.h
@@ -0,0 +1,2470 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "test.h"
+// This function tests all member functions in the four assocative
+// containers and their iterators. The containers are db_map,
+// db_multimap, db_set, db_multiset . They are equivalent to std::map,
+// hash_map, std::multimap, hash_multimap, std::set, hash_set,
+// std::multiset, hash_multiset respectively---passing btree db handles,
+// they are equivalent to std assocative container; passing hash db handles
+// they are hash associative containers
+//
+// This function tests the classes also in pair with std/hash counterparts,
+// but the result of some operations are checked not by comparing contents
+// after operation, but by self-check, often use another member function of
+// the same class to verify. Also, only the four container types in std is
+// used, the hash containers are not standarized, so not used, although
+// hash db type can be passed in, so the db_containers can be of hash type
+//
+// Most of the algorithms in std are targeting at a sequential range, while
+// ranges in associative containers are not, so only some read only
+// algorithms are applied to the db_map container.
+//
+// This function also tests some advanced features, like using containers
+// with secondary db, bulk retrieval, varying length records storage/load,
+// storing native char*/wchar_t* strings, etc
+//
+
+static int hcmp_def(Db *pdb, const Dbt *dbt1, const Dbt *dbt2)
+{
+ u_int32_t sz1 = dbt1->get_size(), sz2 = dbt2->get_size();
+
+ int ret = memcmp(dbt1->get_data(), dbt2->get_data(), sz1 < sz2 ? sz1 : sz2);
+ ret = (ret == 0) ? (sz1 - sz2) : ret;
+
+ return ret;
+}
+
+class TestAssoc
+{
+public:
+ typedef map<int, int> m_int_t;
+ typedef ptint tpint;
+ ~TestAssoc();
+ TestAssoc(void *param1);
+ void start_test()
+ {
+ tb.begin("db_map");
+ test_map_member_functions();
+ test_map_std_functions();
+ test_hot_dbclose();
+ test_arbitrary_object_storage();
+ test_storing_std_strings();
+ test_secondary_containers();
+ tb.end();
+
+ tb.begin("db_multimap");
+ test_mmap_member_functions();
+ tb.end();
+
+ tb.begin("db_set");
+ test_set_member_functions();
+ tb.end();
+
+ tb.begin("db_multiset");
+ test_mset_member_functions();
+ tb.end();
+
+ tb.begin("Special functionalities of all dbstl containers.");
+ test_char_star_string_storage();
+ test_fixed_len_obj_storage();
+ test_arbitray_sequence_storage();
+ test_bulk_retrieval_read();
+ test_nested_txns();
+ test_etc();
+ tb.end();
+
+
+ }
+private:
+ // Test all member functions of db_map<>
+ void test_map_member_functions();
+
+ // Use std functions to manipulate db_map containers.
+ void test_map_std_functions();
+
+ // Close a live container's db handle then open it again and
+ // reassign to the same container, verify the container works.
+ void test_hot_dbclose();
+
+ // Use two ways to store an object of arbitrary length. The object
+ // contains some varying length members, char* string for example.
+ void test_arbitrary_object_storage();
+
+ void test_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 test_secondary_containers();
+
+ // Test all member functions of db_multimap<>.
+ void test_mmap_member_functions();
+
+ // Test all member functions of db_set<>.
+ void test_set_member_functions();
+
+ // Test all member functions of db_multiset<>.
+ void test_mset_member_functions();
+
+ // Test direct storage of char* strings.
+ void test_char_star_string_storage();
+
+ // Testing storage of fixed length objects.
+ void test_fixed_len_obj_storage();
+
+ // Testing storage of arbitrary element type of sequence.
+ void test_arbitray_sequence_storage();
+
+ // Testing reading with bulk retrieval flag.
+ void test_bulk_retrieval_read();
+
+ // Testing nested transaction implementation.
+ void test_nested_txns();
+
+ // Testing miscellaneous functions.
+ void test_etc();
+
+ int flags, setflags, EXPLICIT_TXN, TEST_AUTOCOMMIT, n;
+ DBTYPE dbtype;
+ dm_int_t::difference_type oddcnt;
+ Db *dmdb1, *dmdb2, *dmmdb1, *dmmdb2, *dmsdb1,
+ *dmsdb2, *dmmsdb1, *dmmsdb2, *dbstrv;
+ Db *dbp3;
+ Db *dmdb6;
+ Db *dbp3sec;
+ Db *dmmdb4, *dbstrmap;
+ Db *dmstringdb;
+ DbEnv *penv;
+ u_int32_t dboflags;
+
+ test_block tb;
+ map<int, int> m1;
+ multimap<int, int> mm1;
+};
+
+TestAssoc::~TestAssoc()
+{
+ dbstl::close_db_cursors(this->dmsdb2);
+ dbstl::close_db_cursors(this->dmdb1);
+ dbstl::close_db_cursors(this->dmdb2);
+ dbstl::close_db_cursors(this->dmdb6);
+ dbstl::close_db_cursors(this->dmmdb1);
+}
+
+TestAssoc::TestAssoc(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);
+ dbp3 = NULL;
+
+}
+
+void TestAssoc::test_map_member_functions()
+{
+ int i;
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ dm_int_t dm1(dmdb1, penv);
+ const dm_int_t& cnstdm1 = dm1;
+ dm_int_t simple_map;
+ map<ptint, ptint> ssimple_map;
+ map<ptint, ptint>::iterator sitr, sitr1;
+
+ for (i = 0; i < n; i++) {
+ dm1[i] = ptint(i);
+ ssimple_map[i] = ptint(i);
+ }
+
+ for (i = 0; i < n; i++) {
+ dm_int_t::const_iterator citr, citr1;
+ dm_int_t::iterator itr;
+
+ citr = dm1.find(i);
+ check_expr(citr->second == dm1.find(i)->second);
+ itr = citr;
+ check_expr(*citr == *itr);
+ itr->second = i * 2 + 1;
+ citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(citr->second == dm1.find(i)->second);
+ }
+
+ for (i = 0; i < n; i++) {
+ dm_int_t::const_iterator citr = dm1.find(i);
+ check_expr(citr->second == dm1.find(i)->second);
+ dm_int_t::iterator itr = citr;
+ check_expr(*citr == *itr);
+ itr->second = i * 2 + 1;
+ dm_int_t::const_iterator citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(citr->second == dm1.find(i)->second);
+ }
+
+ for (i = 0; i < n; i++) {
+ dm_int_t::iterator ncitr, ncitr1;
+ dm_int_t::const_iterator citr, citr1;
+
+ ncitr = cnstdm1.find(i);
+ check_expr(ncitr->second == cnstdm1.find(i)->second);
+ citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*ncitr = i * 2 + 1;
+ citr1 = ncitr;
+ ncitr1 = citr1;
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(citr->second == cnstdm1.find(i)->second);
+ }
+
+ for (i = 0; i < n; i++) {
+
+ dm_int_t::iterator ncitr = cnstdm1.find(i);
+ check_expr(ncitr->second == cnstdm1.find(i)->second);
+ dm_int_t::const_iterator citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*itr = i * 2 + 1;
+ dm_int_t::const_iterator citr1 = ncitr;
+ dm_int_t::iterator ncitr1 = citr1;
+
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(citr->second == cnstdm1.find(i)->second);
+ }
+
+ if (dm1.is_hash() == false)
+ {
+ dm1.clear();
+ ssimple_map.clear();
+ for (i = 0; i < n; i++) {
+ dm1[i] = ptint(i);
+ ssimple_map[i] = ptint(i);
+ }
+ dm_int_t::iterator ncitr = dm1.end();
+ dm_int_t::iterator ncrend = --dm1.begin();
+ map<ptint, ptint>::iterator sitr = ssimple_map.end();
+ for (sitr--, --ncitr; ncitr != ncrend; ncitr--, sitr--) {
+ ncitr.refresh(true); // not needed because by default we are using direct db get, only for test purpose.
+ check_expr(*sitr == *ncitr);
+ }
+ ncitr.close_cursor();
+
+ const dm_int_t&cnstdm1 = dm1;
+ dm_int_t::const_iterator citr = cnstdm1.end();
+ dm_int_t::const_iterator crend = --cnstdm1.begin();
+ map<ptint, ptint>::iterator sitr2;
+ map<ptint, ptint>::reverse_iterator rsitr;
+
+ sitr = ssimple_map.end();
+ for (sitr--, --citr; citr!= crend; sitr--, citr--) {
+ citr.refresh(true); // not needed because by default we are using direct db get, only for test purpose.
+ check_expr(*sitr == *citr);
+ }
+
+ for (sitr2 = --ssimple_map.begin(), citr = crend; citr != cnstdm1.end();) {
+ citr++;
+ sitr2++;
+ check_expr(*sitr2 == *citr);
+ }
+
+ simple_map.insert(simple_map.begin(), *ssimple_map.begin());
+ check_expr(*simple_map.begin() == *ssimple_map.begin());
+ crend = --cnstdm1.begin();
+ --(--crend);
+ ++crend;
+ check_expr(*crend == *cnstdm1.begin());
+ citr.close_cursor();
+
+ simple_map.clear();
+ simple_map.insert(cnstdm1.begin(), cnstdm1.end());
+ rsitr = ssimple_map.rbegin();
+ for (dm_int_t::reverse_iterator itrr1 = simple_map.rbegin(); itrr1 != simple_map.rend(); ++itrr1, ++rsitr)
+ check_expr(*itrr1 == *rsitr);
+
+ const dm_int_t &csimple_map = simple_map;
+ rsitr = ssimple_map.rbegin();
+ for (dm_int_t::const_reverse_iterator citrr1 = csimple_map.rbegin(); citrr1 != csimple_map.rend(); ++citrr1, ++rsitr)
+ check_expr((citrr1->first == rsitr->first) && (citrr1->second == rsitr->second));
+
+ for (sitr = ssimple_map.begin(); sitr != ssimple_map.end(); ++sitr)
+ check_expr(csimple_map[sitr->first] == sitr->second);
+
+ simple_map.erase(simple_map.end());
+ check_expr(simple_map.size() == ssimple_map.size());
+ check_expr(csimple_map.find(123) == csimple_map.end());
+
+ check_expr(*csimple_map.lower_bound(1) == *ssimple_map.lower_bound(1));
+ check_expr(*csimple_map.upper_bound(5) == *ssimple_map.upper_bound(5));
+ pair<dm_int_t::const_iterator, dm_int_t::const_iterator> cnsteqrg = csimple_map.equal_range(3);
+ check_expr(cnsteqrg.first->first == 3 && cnsteqrg.second->first == ssimple_map.equal_range(3).second->first);
+
+ }
+ dm1.clear();
+ ssimple_map.clear();
+
+ if (!dm1.is_hash()) {
+ for (i = 0; i < n; i++) {
+ dm1[i] = ptint(i);
+ ssimple_map[i] = ptint(i);
+ }
+ dm_int_t::iterator itr, itr1;
+
+ itr = dm1.find(3);
+ itr1 = dm1.find(8);
+ sitr = ssimple_map.find(3);
+ sitr1 = ssimple_map.find(8);
+
+ dm1.erase(itr, itr1);
+ ssimple_map.erase(sitr, sitr1);
+ pprint(dm1, "dm1 after erasing range: ");
+ check_expr(is_equal(dm1, ssimple_map));
+ dm1.clear();
+ ssimple_map.clear();
+ }
+ for (i = 0; i < 10; i++) {
+ simple_map.insert(make_pair(ptint(i), ptint(i)));
+ ssimple_map.insert(make_pair(ptint(i), ptint(i)));
+ }
+ for (i = 0; i < 10; i++)
+ check_expr(simple_map[i] == ssimple_map[i]);
+
+ dm1.clear();
+ // db_map<>::empty
+ check_expr(dm1.empty());
+ fill(dm1, m1, i = 3, n = 5);
+ check_expr(!dm1.empty());
+
+ dm_int_t::iterator dmi, dmi2;
+ m_int_t::iterator mi;
+ dm_int_t::reverse_iterator dmri;
+ m_int_t::reverse_iterator mri;
+ ptint ptmp;
+ int itmp;
+
+
+ // db_map<>::find, count
+ for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() &&
+ mi !=m1.end(); dmi++, mi++, i++) {
+ // check_expr both contain
+ check_expr((dm1.find(i) != dm1.end()) &&
+ (m1.find(i) != m1.end()));
+
+ pair<dm_int_t::iterator, dm_int_t::iterator> erp =
+ dm1.equal_range(i);
+ int jc = 0;
+ dm_int_t::iterator jj;
+ for (jj = erp.first, jc = 0;
+ jj != erp.second; jj++, jc++)
+ check_expr((*jj).second == ptint(i));
+ check_expr(jc == 1);
+ if (i < 7 && !dm1.is_hash()) {// 7 is last element
+ check_expr((*(dm1.upper_bound(i))).second == i + 1);
+ check_expr((*(dm1.lower_bound(i))).second == i);
+ }
+ else if (i == 7 && !dm1.is_hash()) {
+ check_expr(dm1.upper_bound(i) == dm1.end());
+ check_expr((*(dm1.lower_bound(i))).second == i);
+ } else if (!dm1.is_hash())
+ check_expr(false);
+
+ check_expr(dm1.count(i) == 1);
+ check_expr(dm1.count(-i) == 0);
+ check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
+
+ // order of elements in hash can not be expected
+ if (!dm1.is_hash())
+ check_expr((*dmi).second == (*mi).second);
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmi != dm1.end(); mi--, i--) {
+ // check_expr both contains
+ check_expr((*(dm1.find(i))).second == i);
+ check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
+ // order of elements in hash can not be
+ // expected
+ if (!dm1.is_hash())
+ check_expr((*dmi).second == (*mi).second);
+ if (i % 2)
+ dmi--;
+ else
+ --dmi;
+ }
+ break;
+ }
+
+ }
+ for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3;
+ dmri != dm1.rend() && mri != m1.rend(); dmri++, mri++, i++) {
+ check_expr((dm1.find(i) != dm1.end()) &&
+ (m1.find(i) != m1.end()));// check_expr both contain
+
+ check_expr(dm1[i] == m1[i]);
+ if (!dm1.is_hash())
+ check_expr((*dmri).second == (*mri).second);
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmri != dm1.rend(); mri--, i--) {
+ // check_expr both contain
+ check_expr((*(dm1.find(i))).second == i);
+ // order of elements in hash can not be expected
+ if (!dm1.is_hash())
+ check_expr((*dmri).second == (*mri).second);
+ check_expr((ptmp = dm1[i]) == (itmp = m1[i]));
+ if (i % 2)
+ dmri--;
+ else
+ --dmri;
+ if (i == 3)
+ break;
+ }
+ break;
+ }
+
+ }
+ for (dmi = dm1.begin(), mi = m1.begin(), i = 3; dmi != dm1.end() &&
+ mi !=m1.end(); ++dmi, mi++)
+ i++;
+ check_expr(i == 3 + n);// i must have been incremented to 8
+ for (dmri = dm1.rbegin(), mri = m1.rbegin(), i = 3;
+ dmri != dm1.rend() && mri !=m1.rend(); ++dmri, mri++)
+ i++;
+ check_expr(i == 3 + n);// i must have been incremented to 8
+
+
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+ if (!TEST_AUTOCOMMIT)
+ begin_txn(0, penv);
+ dm_int_t dm2(dmdb2, penv);
+ dm2.clear();
+ if (!TEST_AUTOCOMMIT)
+ commit_txn(penv);
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ dm2.insert(dm1.begin(), dm1.end());
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+ if (!TEST_AUTOCOMMIT)
+ begin_txn(0, penv);
+ dm_int_t dm3 = dm2;
+ if (!TEST_AUTOCOMMIT)
+ commit_txn(penv);
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ check_expr(dm3 == dm2);
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+ if (!TEST_AUTOCOMMIT)
+ begin_txn(0, penv);
+ dm3 = dm1;
+ if (!TEST_AUTOCOMMIT)
+ commit_txn(penv);
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ check_expr(dm3 == dm1);
+ // this test case should be fine for hash because hash config is
+ // identical in dm1 and dm2
+ for (dmi = dm1.begin(), dmi2 = dm2.begin(); dmi != dm1.end() &&
+ dmi2 != dm2.end(); ++dmi, dmi2++)
+ check_expr(*dmi == *dmi2);
+ int arr1[] = {33, 44, 55, 66, 77};
+
+ for (dmi = dm1.begin(), i = 0; dmi != dm1.end(); dmi++, i++)
+ (*dmi).second = tpint(arr1[i]);
+
+ for (dmi = dm1.begin(), dmi2 = dm2.begin(), i = 0;
+ dmi != dm1.end() && dmi2 != dm2.end(); dmi++, i++, dmi2++) {
+ check_expr((*dmi).second == tpint(arr1[i]));
+ dmi2->second = dmi->second;
+ check_expr(*dmi == *dmi2);
+ }
+ // db_map<>::insert(const value_type&). the range insert is already
+ // tested in fill
+ //
+ pair<dm_int_t::iterator, bool> res =
+ dm1.insert(make_pair(3, tpint(33)));
+ check_expr((*(res.first)).first == 3 && res.second == false);
+ // we don't know which value is assigned to key 3 on hash
+ if (!dm1.is_hash())
+ check_expr((*(res.first)).second == 33);
+
+ // db_map<>::count, insert, erase, find
+ check_expr(dm1.count(3) == 1);
+ check_expr(dm1.size() == (size_t)n);// n is 5
+ check_expr(dm1.count(9) == 0);
+ res = dm1.insert(make_pair(9, tpint(99)));
+ check_expr((*(res.first)).second == 99 && (*(res.first)).first == 9 &&
+ res.second == true);
+ check_expr(dm1.count(9) == 1);
+ check_expr(dm1.size() == (size_t)n + 1);
+
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dm1.erase(9);
+ if (!TEST_AUTOCOMMIT)
+ commit_txn(penv);
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+
+ check_expr(dm1.size() == (size_t)n);
+ check_expr(dm1.count(9) == 0);
+ dm1.erase(dm1.find(3));
+ check_expr(dm1.size() == (size_t)n - 1);
+ check_expr(dm1.count(3) == 0);
+ dm2.erase(dm2.begin(), dm2.end());
+ check_expr(dm2.size() == 0);
+ check_expr(dm2.empty());
+
+ dmi = dm1.begin();
+ dmi++;
+ dmi2 = dmi;
+ dmi2++;
+ dmi2++;
+
+ if (dm1.is_hash()) {
+ check_expr(dm1.key_eq()(3, 4) == false);
+ check_expr(dm1.key_eq()(3, 3) == true);
+ check_expr(dm1.bucket_count() != 0);
+ } else
+ check_expr(dm1.key_comp()(3, 4));
+
+ if (dm1.is_hash()) {
+ check_expr(dm1.key_eq()(3, 4) == false);
+ check_expr(dm1.key_eq()(3, 3) == true);
+ } else {
+ check_expr(dm1.key_comp()(3, 4));
+ }
+
+ check_expr(dm1.value_comp()(*dmi, *dmi2));
+ if (dm1.is_hash())
+ cout<<"hash value for key = 3 is: "
+ <<dm1.hash_funct()(3);
+
+ dm2.insert(dmi, dmi2);// 2 recs inserted, [dmi, dmi2)
+ check_expr(dm2.size() == 2);
+ for (dmi = dm1.begin(); dmi != dm1.end(); dmi++)
+ cout<<'\t'<<dmi->first<<'\t'<<dmi->second<<endl;
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT) {
+ begin_txn(0, penv);
+ }
+ dm1.swap(dm2);
+ if (!TEST_AUTOCOMMIT) {
+ commit_txn(penv);
+ }
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ size_t dm1sz, dm2sz;
+ check_expr((dm1sz = dm1.size()) == 2 &&
+ (dm2sz = dm2.size()) == (size_t)n - 1);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT) {
+ begin_txn(0, penv);
+ }
+ dm1.clear();
+ dm2.clear();
+ dm3.clear();
+ if (!TEST_AUTOCOMMIT) {
+ commit_txn(penv);
+ }
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ fill(dm1, m1, i = 3, n = 5);
+ dm1sz = dm1.size();
+ for (i = (int)dm1sz -1; i >0; i--) {
+ dm1[i - 1] = dm1[i];
+ m1[i - 1] = m1[i];
+ }
+ if (!dm1.is_hash())
+ check_expr (is_equal(dm1, m1));
+ dm1[421] = 421;
+ check_expr(dm1.count(421) == 1);
+ m1[421] = 421;
+ int j;
+ for (i = 0; i < 100; i++) {
+ j = rand() ;
+ dm1[i] = i * j;
+#ifdef TEST_PRIMITIVE
+ m1[i] = ((ptint)dm1[i]);
+#else
+ m1[i] = ((ptint)dm1[i]).v;
+#endif
+ }
+ check_expr(dm1.size() == m1.size());
+ if (!dm1.is_hash())
+ check_expr (is_equal(dm1, m1));
+
+ for (i = 0; i < 99; i++) {
+ dm1[i] = dm1[i + 1];
+ m1[i] = m1[i + 1];
+ }
+ if (!dm1.is_hash())
+ check_expr (is_equal(dm1, m1));
+ dm1.clear();
+ m1.clear();
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+} // test_map_member_functions
+
+void TestAssoc::test_map_std_functions()
+{
+ int i;
+
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ dm_int_t dm1(dmdb1, penv);
+ // the following test assumes dm1 and m1 contains
+ // (6,6), (7,7),...(14,14)
+ for(i = 6; i < 15; i++) {
+ dm1[i] = i;
+ m1[i] = i;
+ }
+ dm_int_t::iterator mpos, mpos2;
+ dm_int_t::reverse_iterator mrpos, mrpos2;
+// for_each
+ cout<<"\n_testing std algorithms applied to db_map...\n";
+ cout<<"\nfor_each begin to end\n";
+ for_each(dm1.begin(), dm1.end(), square_pair<dm_int_t::value_type_wrap>);
+ cout<<endl;
+ for_each(m1.begin(), m1.end(), square_pair2<map<int, int>::value_type>);
+ cout<<"\nfor_each begin +1 to end\n";
+ for_each(dm1.begin() ++, (dm1.begin()--)--, square_pair<dm_int_t::value_type_wrap>);
+ cout<<endl;
+ for_each(m1.begin() ++, (m1.begin() --)--, square_pair2<map<int, int>::value_type>);
+
+ //find
+ ptint tgt(12);
+ mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt));
+ check_expr(mpos != dm1.end() && ((mpos->second) == tgt));
+ mpos = find(++(dm1.begin() ++), --(dm1.end() --), make_pair(tgt, tgt));
+ check_expr(mpos != dm1.end() && ((mpos->second) == tgt));
+ tgt = -123;
+ mpos = find(dm1.begin(), dm1.end(), make_pair(tgt, tgt));
+ check_expr(mpos == dm1.end());
+ pair<int, int>* subseq3 = new pair<int, int>[3];
+ subseq3[0] = make_pair(8, 8);
+ subseq3[1] = make_pair(9, 9);
+ subseq3[2] = make_pair(10, 10);
+ pair<int, int>* subseq4 = new pair<int, int>[4];
+ subseq4[0] = make_pair(9, 9);
+ subseq4[1] = make_pair(8, 8);
+ subseq4[2] = make_pair(10, 10);
+ subseq4[3] = make_pair(11, 11);
+ // find_end
+ if (!dm1.is_hash()) {
+#ifdef WIN32
+ mpos = find_end(dm1.begin(), dm1.end(), dm1.begin(), ++(dm1.begin()) );
+ check_expr(mpos == dm1.begin());
+ mpos = find_end(dm1.begin(), dm1.end(), mpos2 = ++(++(dm1.begin()++)),
+ --(--(dm1.end()--)));
+ check_expr(mpos == mpos2);
+
+ mpos = find_end(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3);
+ check_expr(mpos == ++(++(dm1.begin())));
+#endif
+ // find_first_of
+ mpos = find_first_of(dm1.begin(), dm1.end(), dm1.begin(),
+ ++dm1.begin());
+ check_expr(mpos == dm1.begin());
+
+ mpos = find_first_of(++dm1.begin(), --dm1.end(),
+ subseq4, subseq4 + 4);
+ check_expr(mpos == ++(++dm1.begin()));
+ mpos = find_first_of(--(--dm1.end()), dm1.end(),
+ subseq4, subseq4 + 4);
+ check_expr(mpos == dm1.end());
+
+ // mismatch
+
+ pair<dm_int_t::iterator , pair<int, int>*> resmm2 = mismatch(dm1.begin(),
+ ++(++(++dm1.begin())), subseq3);
+ check_expr(resmm2.first == dm1.begin() && resmm2.second == subseq3);
+
+ //search
+ mpos = search(dm1.begin(), dm1.end(), dm1.begin(), ++dm1.begin());
+ check_expr(mpos == dm1.begin());
+ mpos = search(++dm1.begin(), dm1.end(), subseq3, subseq3 + 3);
+ check_expr(mpos == ++(++dm1.begin()));
+ //equal
+ mpos2 = dm1.begin();
+ mpos2.move_to(8);
+ check_expr (equal(dm1.begin(), mpos2, subseq3) == false);
+ mpos = mpos2; mpos.move_to(11);
+ check_expr(equal(mpos2, mpos, subseq3) == true);
+ mpos.move_to(10);
+ check_expr(equal(mpos2, mpos, subseq3) == true);
+ }
+ delete [] subseq4;
+ delete [] subseq3;
+ //find_if
+ mpos = find_if(dm1.begin(), dm1.end(), is2digits_pair);
+ check_expr(ptint(mpos->second) == 10);
+
+ // count_if
+ oddcnt = count_if(dm1.begin(), dm1.end(), is_odd_pair);
+ check_expr(oddcnt == 4);
+ oddcnt = count_if(dm1.begin(), dm1.begin(), is_odd_pair);
+ check_expr(oddcnt == 0);
+
+
+ if ( EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+
+} // test_map_std_functions
+
+void TestAssoc::test_hot_dbclose()
+{
+ int i;
+ map<ptint, ptint> m2;
+ dm_int_t dm2(dmdb2, penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dm2.clear();// can be auto commit
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ for (i = 0; i < 5; i++) {
+ dm2[i] = i;
+ m2[i] = i;
+ }
+
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+ dm_int_t dm1(dmdb1, penv);
+ dbstl::close_db(dm1.get_db_handle());
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ dm1.set_db_handle(dbp3 = dbstl::open_db(penv, "db_map.db",
+ dbtype, DB_CREATE | dboflags, 0));
+ if (!dm1.is_hash())
+ check_expr (is_equal(dm1, m1));
+ dm1.clear();
+ if (EXPLICIT_TXN)
+ commit_txn(penv);
+} // test_hot_dbclose
+
+void TestAssoc::test_arbitrary_object_storage()
+{
+ int i;
+
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ // varying length objects test
+ cout<<"\n_testing arbitary 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);
+ // check that retrieved data is identical to stored data
+ 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<<"\n_testing arbitary 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);
+} // test_arbitrary_object_storage
+
+// std::string persistent test.
+void TestAssoc::test_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 TestAssoc::test_secondary_containers()
+{
+ int i;
+
+ if (EXPLICIT_TXN)
+ begin_txn(0, penv);
+ // test secondary db
+ cout<<"\n_testing db 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);
+
+} // test_secondary_containers
+
+void TestAssoc::test_mmap_member_functions()
+{
+ // db_multimap<>
+ int i;
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ dmm_int_t dmm1(dmmdb1, penv);
+
+ dmm1.clear();
+ // db_multimap<>::empty
+ check_expr(dmm1.empty());
+ {
+ size_t sz0, szeq1, szeq2;
+
+ fill(dmm1, mm1, i = 3, n = 5, 4);
+ const dmm_int_t &cdmm1 = dmm1;
+ dmm_int_t dmmn(NULL, penv);
+ dmmn.insert(cdmm1.begin(), cdmm1.end());
+ check_expr(!(dmmn != cdmm1));
+
+ pair<dmm_int_t::const_iterator, dmm_int_t::const_iterator> cnstrg, ceqrgend;
+ pair<dmm_int_t::iterator, dmm_int_t::iterator> nceqrg, eqrgend;
+
+ for (i = 3; i < 8; i++) {
+ cnstrg = cdmm1.equal_range(i);
+ nceqrg = dmm1.equal_range(i);
+ dmm_int_t::const_iterator cmmitr;
+ dmm_int_t::iterator mmitr;
+ for (sz0 = 0, cmmitr = cnstrg.first, mmitr = nceqrg.first; mmitr != nceqrg.second; mmitr++, cmmitr++, sz0++)
+ check_expr(*cmmitr == *mmitr);
+ check_expr(cmmitr == cnstrg.second);
+ if (i < 7)
+ check_expr(*(cdmm1.upper_bound(i)) == *(dmm1.upper_bound(i)));
+ cnstrg = cdmm1.equal_range_N(i, szeq1);
+ nceqrg = dmm1.equal_range_N(i, szeq2);
+ check_expr(szeq1 == szeq2 && szeq2 == sz0);
+ }
+ eqrgend = dmm1.equal_range(65535);
+ check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end());
+ eqrgend = dmm1.equal_range_N(65535, szeq1);
+ check_expr(eqrgend.first == dmm1.end() && eqrgend.second == dmm1.end() && szeq1 == 0);
+ ceqrgend = cdmm1.equal_range(65535);
+ check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end());
+ ceqrgend = cdmm1.equal_range_N(65535, szeq1);
+ check_expr(ceqrgend.first == cdmm1.end() && ceqrgend.second == cdmm1.end() && szeq1 == 0);
+ if (!dmm1.is_hash()) {
+ eqrgend = dmm1.equal_range(2);
+ check_expr((((eqrgend.first))->first == 3) && ((eqrgend.second))->first == 3);
+ ceqrgend = cdmm1.equal_range(2);
+ check_expr(((ceqrgend.first))->first == 3 && ((ceqrgend.second))->first == 3);
+ eqrgend = dmm1.equal_range_N(2, szeq1);
+ check_expr((eqrgend.first)->first == 3 && ((eqrgend.second))->first == 3 && szeq1 == 0);
+ ceqrgend = cdmm1.equal_range_N(2, szeq1);
+ check_expr((ceqrgend.first)->first == 3 && ((ceqrgend.second))->first == 3 && szeq1 == 0);
+
+ check_expr(((dmm1.upper_bound(2)))->first == 3);
+ check_expr(((cdmm1.upper_bound(2)))->first == 3);
+ check_expr(dmm1.upper_bound(65535) == dmm1.end());
+ check_expr(cdmm1.upper_bound(65535) == cdmm1.end());
+ check_expr(dmm1.lower_bound(65535) == dmm1.end());
+ check_expr(cdmm1.lower_bound(65535) == cdmm1.end());
+ check_expr(dmm1.count(65535) == 0);
+ check_expr(dmm1.find(65535) == dmm1.end());
+ check_expr(cdmm1.find(65535) == cdmm1.end());
+
+ dmm_int_t tmpdmm0(dmm1);
+ dmm1.erase(dmm1.end());
+ check_expr(dmm1 == tmpdmm0);
+ nceqrg = tmpdmm0.equal_range(5);
+
+ for (dmm_int_t::iterator itr0 = nceqrg.first; itr0 != nceqrg.second; ++itr0)
+ itr0->second *= 2;
+ check_expr(tmpdmm0 != dmm1);
+ tmpdmm0.insert(dmm1.begin(), ++(++dmm1.begin()));
+ check_expr(tmpdmm0 != dmm1);
+ }
+ dmm1.clear();
+ mm1.clear();
+ }
+ fill(dmm1, mm1, i = 3, n = 5, 4);
+ check_expr(!dmm1.empty());
+
+ typedef multimap<int, int> mm_int_t;
+ dmm_int_t::iterator dmmi, dmmi2;
+ mm_int_t::iterator mmi;
+ dmm_int_t::reverse_iterator dmmri;
+ mm_int_t::reverse_iterator mmri;
+
+ print_mm(dmm1, dmmi);
+ // db_multimap<>::find, count
+ for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3;
+ dmmi != dmm1.end() &&
+ mmi !=mm1.end(); dmmi++, mmi++, i++) {
+ // check_expr both contain
+ check_expr((*(dmm1.find(i))).second == i);
+
+ pair<dmm_int_t::iterator, dmm_int_t::iterator> erp1 =
+ dmm1.equal_range(i);
+ int jc = 0;
+ dmm_int_t::iterator jj;
+ for (jj = erp1.first, jc = 0;
+ jj != erp1.second; jj++, jc++)
+ check_expr((*jj).second == ptint(i));
+
+ check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates
+ if (i < 7 && !dmm1.is_hash()) {// 7 is last element
+ check_expr((*(dmm1.upper_bound(i))).second == i + 1);
+ check_expr((*(dmm1.lower_bound(i))).second == i);
+ }
+ else if (i == 7 && !dmm1.is_hash()) {
+ check_expr(dmm1.upper_bound(i) == dmm1.end());
+ check_expr((*(dmm1.lower_bound(i))).second == i);
+ } else if (!dmm1.is_hash())
+ check_expr(false);
+
+ check_expr(dmm1.count(i) == g_count[i]);
+ check_expr(dmm1.count(-i) == 0);
+ if (!dmm1.is_hash())
+ check_expr((*dmmi).second == (*mmi).second);
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmmi != dmm1.end(); mmi--, i--) {
+ // check_expr both contains
+ check_expr((*(dmm1.find(i))).second == i);
+ if (!dmm1.is_hash())
+ check_expr((*dmmi).second == (*mmi).second);
+ if (i % 2)
+ dmmi--;
+ else
+ --dmmi;
+ }
+ break;
+ }
+
+ }
+ for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3;
+ dmmri != dmm1.rend() && mmri !=mm1.rend(); dmmri++, mmri++, i++) {
+ check_expr((dmm1.find(i) != dmm1.end()) &&
+ (mm1.find(i) != mm1.end()));// check_expr both contain
+ if (dmm1.is_hash() == false)
+ check_expr((*dmmri).second == (*mmri).second);
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmmri != dmm1.rend() && mmri != mm1.rend(); i--) {
+ // check_expr both contain
+ check_expr((*(dmm1.find(i))).second == i);
+ if (!dmm1.is_hash())
+ check_expr((*dmmri).second == (*mmri).second);
+ if (i % 2)
+ dmmri--;
+ else
+ --dmmri;
+ if (i > 3) // MS STL bug: when msri points to last element, it can not go back
+ mmri--;
+
+ }
+ break;
+ }
+
+ }
+ for (dmmi = dmm1.begin(), mmi = mm1.begin(), i = 3;
+ dmmi != dmm1.end() &&
+ mmi !=mm1.end(); ++dmmi, mmi++)
+ i++;
+ check_expr((size_t)i == 3 + g_sum(3, 8));
+ for (dmmri = dmm1.rbegin(), mmri = mm1.rbegin(), i = 3;
+ dmmri != dmm1.rend() && mmri !=mm1.rend(); ++dmmri, mmri++)
+ i++;
+ check_expr((size_t)i == 3 + g_sum(3, 8));
+
+ dmm_int_t dmm2(dmmdb2, penv);
+ dmm2.clear();
+ dmmi = dmm1.begin();
+ dmmi2 = dmm1.end();
+ dmm2.insert(dmmi, dmmi2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmm_int_t dmm3 = dmm2;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ check_expr(dmm3 == dmm2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmm3 = dmm1;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ check_expr(dmm3 == dmm1);
+
+ for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(); dmmi != dmm1.end() &&
+ dmmi2 != dmm2.end(); ++dmmi, dmmi2++)
+ check_expr(*dmmi == *dmmi2);
+
+ // content of dmm1 and dmm2 are changed since now
+ int arr1[] = {33, 44, 55, 66, 77};
+ int arr11[] = {33, 44, 55, 66, 77};
+ for (dmmi = dmm1.begin(), i = 0; dmmi != dmm1.end(); dmmi++, i++)
+ (*dmmi).second = tpint(arr11[i % 5]);
+
+ for (dmmi = dmm1.begin(), dmmi2 = dmm2.begin(), i = 0;
+ dmmi != dmm1.end() && dmmi2 != dmm2.end();
+ dmmi++, i++, dmmi2++) {
+ check_expr((*dmmi).second == tpint(arr1[i % 5]));
+ dmmi2->second = dmmi->second;
+ check_expr(*dmmi == *dmmi2);
+ }
+
+ // db_multimap<>::insert(const value_type&). the range insert is already
+ // tested in fill
+ //
+ dmm_int_t::iterator iitr = dmm1.insert(make_pair(3, tpint(33)));
+ check_expr(iitr->first == 3);
+ // the returned iitr points to any rec with key==3, not necessarily
+ // the newly inserted rec, so not sure of the value on hash
+ if (dmm1.is_hash() == false)
+ check_expr(iitr->second == 33);
+
+ dmm1.clear();
+ mm1.clear();
+ fill(dmm1, mm1, i = 3, n = 5, 4);
+ // db_multimap<>::count, insert, erase, find
+ size_t sizet1;
+ check_expr(dmm1.count(3) == g_count[3]);
+ check_expr(dmm1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8
+ check_expr(dmm1.count(9) == 0);
+ dmm_int_t::iterator iitr2 = dmm1.insert(make_pair(9, tpint(99)));
+ check_expr(iitr2->first == 9 && iitr2->second == 99);
+ check_expr(dmm1.count(9) == 1);
+ check_expr(dmm1.size() == sizet1 + 1);
+ dmm1.erase(9);
+ check_expr(dmm1.size() == (sizet1 = g_sum(3, 8)));
+ check_expr(dmm1.count(9) == 0);
+ dmm1.erase(dmm1.find(3));
+ check_expr(dmm1.size() == g_sum(3, 8) - 1);
+ check_expr(dmm1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0));
+ dmm2.erase(dmm2.begin(), dmm2.end());
+ check_expr(dmm2.size() == 0);
+ check_expr(dmm2.empty());
+
+ dmmi = dmm1.begin();
+ dmmi++;
+ dmmi2 = dmmi;
+ dmmi2++;
+ dmmi2++;
+ size_t sizet2;
+ dmm2.insert(dmmi, dmmi2);// 2 recs inserted, [dmi, dmi2)
+ check_expr((sizet2 = dmm2.size()) == 2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+
+ dmm1.swap(dmm2);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ size_t dmm1sz, dmm2sz;
+ check_expr((dmm1sz = dmm1.size()) == 2 && (dmm2sz =
+ dmm2.size()) == sizet1 - 1);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmm1.clear();
+ dmm2.clear();
+ dmm3.clear();
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ dmm_int_t dmm4(dmmdb4, penv);
+ dmm4.clear();
+ multimap<ptint, ptint> mm4;
+ int jj;
+ for (i = 0; i < 10; i++) {
+ sizet2 = abs(rand() % 20) + 1;
+ for (jj = 0; jj < (int)sizet2; jj++) {
+ dmm4.insert(make_pair(i, jj));
+ mm4.insert(make_pair(i, jj));
+ }
+ }
+ pair<dmm_int_t::iterator, dmm_int_t::iterator> eqrgdmm;
+ pair<multimap<ptint, ptint>::iterator, multimap<ptint, ptint>::iterator>
+ eqrgmm;
+ dmm_int_t::iterator dmmitr;
+ multimap<ptint, ptint>::iterator mmitr;
+ for (i = 0; i < 10; i++) {
+ eqrgdmm = dmm4.equal_range(i);
+ eqrgmm = mm4.equal_range(i);
+ for (dmmitr = eqrgdmm.first, mmitr = eqrgmm.first; dmmitr !=
+ eqrgdmm.second && mmitr != eqrgmm.second; dmmitr++, mmitr++)
+ check_expr(*dmmitr == *mmitr);
+ check_expr((dmmitr == eqrgdmm.second) && (mmitr == eqrgmm.second));
+ }
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+} // test_mmap_member_functions
+
+void TestAssoc::test_set_member_functions()
+{
+// db_set<>
+ int i;
+ int arr1[] = {33, 44, 55, 66, 77};
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ dms_int_t dms1(dmsdb1, penv);
+ const dms_int_t& cnstdms1 = dms1;
+ set<ptint> ms1;
+
+ n = 10;
+ for (i = 0; i < n; i++)
+ dms1.insert(i);
+
+ for (i = 0; i < n; i++) {
+ dms_int_t::const_iterator citr, citr1;
+ citr = dms1.find(i);
+ check_expr(*citr == *dms1.find(i));
+ dms_int_t::iterator itr = citr;
+ check_expr(*citr == *itr);
+ *itr = i;
+ itr = dms1.find(i);
+ citr = itr;
+ citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == *dms1.find(i));
+ }
+
+ for (i = 0; i < n; i++) {
+ dms_int_t::const_iterator citr = dms1.find(i);
+ check_expr(*citr == *dms1.find(i));
+ dms_int_t::iterator itr = citr;
+ check_expr(*citr == *itr);
+ *itr = i;
+ itr = dms1.find(i);
+ citr = itr;
+ dms_int_t::const_iterator citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == *dms1.find(i));
+ }
+
+ for (i = 0; i < n; i++) {
+ dms_int_t::iterator ncitr, ncitr1;
+ dms_int_t::const_iterator citr, citr1;
+
+ ncitr = cnstdms1.find(i);
+ check_expr(*ncitr == *cnstdms1.find(i));
+ citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*ncitr = i * 2 + 1;
+ citr1 = ncitr;
+ ncitr1 = citr1;
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == *cnstdms1.find(i));
+ }
+
+ for (i = 0; i < n; i++) {
+
+ dms_int_t::iterator ncitr = cnstdms1.find(i);
+ check_expr(*ncitr == *cnstdms1.find(i));
+ dms_int_t::const_iterator citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*itr = i * 2 + 1;
+ dms_int_t::const_iterator citr1 = ncitr;
+ dms_int_t::iterator ncitr1 = citr1;
+
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == *cnstdms1.find(i));
+ }
+
+ if (dms1.is_hash() == false)
+ {
+ ms1.clear();
+ dms1.clear();
+ for (i = 0; i < n; i++) {
+ dms1.insert(ptint(i));
+ ms1.insert(ptint(i));
+ }
+
+ const dms_int_t &cnstdms1 = dms1;
+ dms_int_t tmpdms0;
+
+ tmpdms0.insert(cnstdms1.begin(), cnstdms1.end());
+ dms_int_t::const_iterator citr = dms1.end(), citr2 = --dms1.begin(), itr2;
+ set<ptint>::const_iterator scitr = ms1.end(), scitr2 = --ms1.begin();
+ for (citr--, scitr--; citr != citr2; --citr, --scitr) {
+ check_expr(*citr == *scitr);
+ }
+ check_expr(scitr == scitr2);
+
+ db_set<ptype<int> > dmspt;
+ dmspt.insert(cnstdms1.begin(), cnstdms1.end());
+
+ db_set<ptype<int> >::const_iterator itrpt;
+ db_set<ptype<int> >::iterator itrpt2;
+
+ for (itrpt = dmspt.begin(), citr = dms1.begin(); itrpt != dmspt.end(); ++itrpt, ++citr) {
+ itrpt.refresh(true);
+ check_expr(itrpt->v == *citr);
+ }
+
+ for (itrpt2 = dmspt.begin(), itr2 = dms1.begin(); itrpt2 != dmspt.end(); ++itrpt2, ++itr2) {
+ itrpt2.refresh(true);
+ check_expr(itrpt2->v == *itr2);
+ }
+
+ dms_int_t dmstmp(dms1);
+ check_expr(dms1 == dmstmp);
+ dms1.insert(dms1.begin(), 101);
+ check_expr(dms1 != dmstmp);
+
+ ms1.clear();
+ dms1.clear();
+ }
+ dms1.clear();
+ // db_map<>::empty
+ check_expr(dms1.empty());
+ fill(dms1, ms1, i = 3, n = 5);
+ check_expr(!dms1.empty());
+
+ typedef set<int> ms_int_t;
+ dms_int_t::iterator dmsi, dmsi2;
+ ms_int_t::iterator msi;
+ dms_int_t::reverse_iterator dmsri;
+ ms_int_t::reverse_iterator msri;
+
+ // db_set<>::find, count
+ for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() &&
+ msi !=ms1.end(); dmsi++, msi++, i++) {
+ // check_expr both contain
+ check_expr(*(dms1.find(i)) == i);
+
+ pair<dms_int_t::iterator, dms_int_t::iterator> erp =
+ dms1.equal_range(i);
+ int jc = 0;
+ dms_int_t::iterator jj;
+ for (jj = erp.first, jc = 0;
+ jj != erp.second; jj++, jc++)
+ check_expr((*jj) == ptint(i));
+ check_expr(jc == 1);
+ if (i < 7 && !dms1.is_hash()) {// 7 is last element
+ check_expr((*(dms1.upper_bound(i))) == i + 1);
+ check_expr((*(dms1.lower_bound(i))) == i);
+ }
+ else if (i == 7 && !dms1.is_hash()) {
+ check_expr(dms1.upper_bound(i) == dms1.end());
+ check_expr((*(dms1.lower_bound(i))) == i);
+ } else if (!dms1.is_hash())
+ check_expr(false);
+
+ check_expr(dms1.count(i) == 1);
+ check_expr(dms1.count(-i) == 0);
+ if (!dms1.is_hash()) {
+ check_expr((*dmsi) == (*msi));
+ check_expr((*dmsi) == (*msi));
+ }
+ if (i == 3 + n - 1) {// last element
+ if (!dms1.is_hash())
+ check_expr((*dmsi) == (*msi));
+ for (; dmsi != dms1.end() && (*dmsi) == (*msi); i--) {
+ // check_expr both contains
+ if (!dms1.is_hash())
+ check_expr((*dmsi) == (*msi));
+ check_expr((*(dms1.find(i)) == i));
+
+ if (i % 2)
+ dmsi--;
+ else
+ --dmsi;
+ msi--;
+ }
+ break;
+ }
+
+ }
+ for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3;
+ dmsri != dms1.rend() && msri != ms1.rend(); dmsri++, msri++, i++) {
+ check_expr((*(dms1.find(i)) == i));
+ if (!dms1.is_hash())
+ check_expr((*dmsri) == (*msri));
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmsri != dms1.rend() && msri != ms1.rend(); i--) {
+ // check_expr both contain
+ check_expr((dms1.find(i) != dms1.end()) &&
+ (ms1.find(i) != ms1.end()));
+ if (!dms1.is_hash())
+ check_expr((*dmsri) == (*msri));
+
+ if (i % 2)
+ dmsri--;
+ else
+ --dmsri;
+ if (i > 3) // MS STL bug: when msri points to last element, it can not go back
+ msri--;
+
+ }
+ break;
+ }
+
+ }
+ for (dmsi = dms1.begin(), msi = ms1.begin(), i = 3; dmsi != dms1.end() &&
+ msi !=ms1.end(); ++dmsi, msi++)
+ i++;
+ check_expr(i == 3 + n);
+
+ for (dmsri = dms1.rbegin(), msri = ms1.rbegin(), i = 3;
+ dmsri != dms1.rend() && msri !=ms1.rend(); ++dmsri, msri++)
+ i++;
+ check_expr(i == 3 + n);
+
+ dms_int_t dms2(dmsdb2, penv);
+ dms2.clear();
+ dms2.insert(dms1.begin(), dms1.end());
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dms_int_t dms3 = dms2;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ check_expr(dms3 == dms2);
+ dms3 = dms1;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ check_expr(dms3 == dms1);
+
+ for (dmsi = dms1.begin(), dmsi2 = dms2.begin(); dmsi != dms1.end() &&
+ dmsi2 != dms2.end(); ++dmsi, dmsi2++)
+ check_expr(*dmsi == *dmsi2);
+
+ /* !!!XXX
+ set keys are not supposed to be mutated, so this is an extra functionality, just like
+ the set iterator assignment in ms's stl library. Here we must use i < dms1.size() to
+ limit the number of loops because after each assignment, dmsi will be positioned to
+ the element which is immediately next to the old key it sits on before the assignment,
+ thus it may take more loops to go to the end() position.
+ */
+ pprint(dms1, "dms1 before iterator assignment : \n");
+ dms_int_t::size_type ui;
+ for (dmsi = dms1.begin(), ui = 0; dmsi != dms1.end() && ui < dms1.size(); dmsi++, ui++) {
+ (*dmsi) = tpint(arr1[ui]);
+ pprint(dms1, "\ndms1 after one element assignment : ");
+ }
+ if (dms1.is_hash() == false) {
+ pprint(dms1, "dms1 after iterator assignment : \n");
+ for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0;
+ dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++) {
+ check_expr((*dmsi) == tpint(arr1[i]));
+ *dmsi2 = *dmsi;
+ // check_expr(*dmsi == *dmsi2); dmsi2 is invalidated by the assignment, so can't compare here.
+ }
+ // Compare here.
+ for (dmsi = dms1.begin(), dmsi2 = dms2.begin(), i = 0;
+ dmsi != dms1.end() && dmsi2 != dms2.end(); dmsi++, i++, dmsi2++)
+ check_expr(*dmsi2 == *dmsi);
+ }
+
+ dms1.clear();
+ //dms2.clear();
+ fill(dms1, ms1, i = 3, n = 5);
+ // db_set<>::insert(const value_type&). the range insert is already
+ // tested in fill
+ //
+ pair<dms_int_t::iterator, bool> ress =
+ dms1.insert(tpint(3));
+ check_expr((*(ress.first)) == 3 && ress.second == false);
+
+ // db_set<>::count, insert, erase, find
+ check_expr(dms1.count(3) == 1);
+ check_expr(dms1.size() == (size_t)n);// n is 5
+ check_expr(dms1.count(9) == 0);
+ ress = dms1.insert(tpint(9));
+ check_expr((*(ress.first)) == 9 && ress.second == true);
+ check_expr(dms1.count(9) == 1);
+ check_expr(dms1.size() == (size_t)n + 1);
+ dms1.erase(9);
+ check_expr(dms1.size() == (size_t)n);
+ check_expr(dms1.count(9) == 0);
+ dms1.erase(dms1.find(3));
+ check_expr(dms1.size() == (size_t)n - 1);
+ check_expr(dms1.count(3) == 0);
+ dms2.erase(dms2.begin(), dms2.end());
+ check_expr(dms2.size() == 0);
+ check_expr(dms2.empty());
+
+ dmsi = dms1.begin();
+ dmsi++;
+ dmsi2 = dmsi;
+ dmsi2++;
+ dmsi2++;
+ dms2.insert(dmsi, dmsi2);// 2 recs inserted, [dmsi, dmsi2)
+ check_expr(dms2.size() == 2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dms1.swap(dms2);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ size_t dms1sz, dms2sz;
+ check_expr((dms1sz = dms1.size()) == 2 && (dms2sz = dms2.size()) == (size_t)n - 1);
+ dms1.clear();
+ dms2.clear();
+ dms3.clear();
+
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+} // test_set_member_functions
+
+void TestAssoc::test_mset_member_functions()
+{
+// db_multiset<>
+ int i;
+ size_t sizet1;
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ dmms_int_t dmms1(dmmsdb1, penv);
+ multiset<int> mms1;
+
+ dmms1.clear();
+ // db_multiset<>::empty
+ check_expr(dmms1.empty());
+ fill(dmms1, mms1, i = 3, n = 5, 4);
+ check_expr(!dmms1.empty());
+ dmms_int_t tmpmms0;
+ const dmms_int_t &cnstmms = dmms1;
+ dmms_int_t tmpmms1;
+ tmpmms1.insert(dmms1.begin(), dmms1.end());
+ tmpmms0.insert(cnstmms.begin(), cnstmms.end());
+ tmpmms0.insert(tmpmms0.begin(), *(--tmpmms0.end()));
+ check_expr(tmpmms0 != tmpmms1);
+
+ typedef multiset<int> mms_int_t;
+ dmms_int_t::iterator dmmsi, dmmsi2;
+ mms_int_t::iterator mmsi;
+ dmms_int_t::reverse_iterator dmmsri;
+ mms_int_t::reverse_iterator mmsri;
+
+ // db_multiset<>::find, count
+ for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3;
+ dmmsi != dmms1.end() &&
+ mmsi !=mms1.end(); dmmsi++, mmsi++, i++) {
+ // check_expr both contain
+ check_expr((*(dmms1.find(i))) == i);
+
+ pair<dmms_int_t::iterator, dmms_int_t::iterator> erp1 =
+ dmms1.equal_range(i);
+ int jc = 0;
+ dmms_int_t::iterator jj;
+ for (jj = erp1.first, jc = 0;
+ jj != erp1.second; jj++, jc++) {
+ // there is bug so this line can be reached
+ if ((size_t)jc == g_count[i]) {
+ jj == erp1.second;// cmp again to debug it
+ dmms1.get_db_handle()->stat_print(DB_STAT_ALL);
+ }
+ check_expr((*jj) == ptint(i));
+ }
+ check_expr((size_t)jc == g_count[i]); // g_count[i] duplicates
+ if (i < 7 && !dmms1.is_hash()) {// 7 is last element
+ check_expr((*(dmms1.upper_bound(i))) == i + 1);
+ check_expr((*(dmms1.lower_bound(i))) == i);
+ }
+ else if (i == 7 && !dmms1.is_hash()) {
+ check_expr(dmms1.upper_bound(i) == dmms1.end());
+ check_expr((*(dmms1.lower_bound(i))) == i);
+ } else if (!dmms1.is_hash())
+ check_expr(false);
+
+ check_expr(dmms1.count(i) == g_count[i]);
+ check_expr(dmms1.count(-i) == 0);
+ if (!dmms1.is_hash())
+ check_expr((*dmmsi) == (*mmsi));
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmmsi != dmms1.end(); mmsi--, i--) {
+ // check_expr both contains
+ check_expr((*(dmms1.find(i))) == i);
+ if (!dmms1.is_hash())
+ check_expr((*dmmsi) == (*mmsi));
+ if (i % 2)
+ dmmsi--;
+ else
+ --dmmsi;
+ }
+ break;
+ }
+
+ }
+ for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3;
+ dmmsri != dmms1.rend() && mmsri !=mms1.rend(); dmmsri++, mmsri++, i++) {
+ check_expr((dmms1.find(i) != dmms1.end()) &&
+ (mms1.find(i) != mms1.end()));// check_expr both contain
+ if (dmms1.is_hash() == false)
+ check_expr((*dmmsri) == (*mmsri));
+ if (i == 3 + n - 1) {// last element
+
+ for (; dmmsri != dmms1.rend() && mmsri != mms1.rend(); i--) {
+ // check_expr both contain
+ check_expr((*(dmms1.find(i))) == i);
+ if (!dmms1.is_hash())
+ check_expr((*dmmsri) == (*mmsri));
+ if (i % 2)
+ dmmsri--;
+ else
+ --dmmsri;
+ if (i > 3) // MS STL bug: when msri points to last element, it can not go back
+ mmsri--;
+ }
+ break;
+ }
+
+ }
+ for (dmmsi = dmms1.begin(), mmsi = mms1.begin(), i = 3;
+ dmmsi != dmms1.end() &&
+ mmsi !=mms1.end(); ++dmmsi, mmsi++)
+ i++;
+ check_expr((size_t)i == 3 + g_sum(3, 8));
+ for (dmmsri = dmms1.rbegin(), mmsri = mms1.rbegin(), i = 3;
+ dmmsri != dmms1.rend() && mmsri !=mms1.rend(); ++dmmsri, mmsri++)
+ i++;
+ check_expr((size_t)i == 3 + g_sum(3, 8));
+
+
+
+
+ dmms_int_t dmms2(dmmsdb2, penv);
+ dmms2.clear();
+ dmms2.insert(dmms1.begin(), dmms1.end());
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmms_int_t dmms3 = dmms2;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ cout<<"\ndmms2: \n";
+ for (dmms_int_t::iterator itr = dmms2.begin(); itr != dmms2.end(); ++itr)
+ cout<<"\t"<<*itr;
+ cout<<"\ndmms3: \n";
+ for (dmms_int_t::iterator itr = dmms3.begin(); itr != dmms3.end(); ++itr)
+ cout<<"\t"<<*itr;
+
+ check_expr(dmms3 == dmms2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmms3 = dmms1;
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ check_expr(dmms3 == dmms1);
+
+ for (dmmsi = dmms1.begin(), dmmsi2 = dmms2.begin(); dmmsi != dmms1.end() &&
+ dmmsi2 != dmms2.end(); ++dmmsi, dmmsi2++)
+ check_expr(*dmmsi == *dmmsi2);
+
+ // content of dmms1 and dmms2 are changed since now
+ // int arr11[] = {33, 44, 55, 66, 77};
+
+ // db_multiset<>::insert(const value_type&). the range insert is already
+ // tested in fill
+ //
+ dmms_int_t::iterator iitrms = dmms1.insert(ptint (3));
+ check_expr(*iitrms == 3);
+
+ dmms1.clear();
+ mms1.clear();
+ fill(dmms1, mms1, i = 3, n = 5, 4);
+ // db_multiset<>::count, insert, erase, find
+ check_expr(dmms1.count(3) == g_count[3]);
+ check_expr(dmms1.size() == (sizet1 = g_sum(3, 8)));// sum of recs from 3 to 8
+ check_expr(dmms1.count(9) == 0);
+ dmms_int_t::iterator iitrms2 = dmms1.insert(ptint (9));
+ check_expr(*iitrms2 == 9);
+ check_expr(dmms1.count(9) == 1);
+ check_expr(dmms1.size() == sizet1 + 1);
+ dmms1.erase(9);
+ check_expr(dmms1.size() == g_sum(3, 8));
+ check_expr(dmms1.count(9) == 0);
+ dmms1.erase(dmms1.find(3));
+ check_expr(dmms1.size() == g_sum(3, 8) - 1);
+ check_expr(dmms1.count(3) == (g_count[3] - 1 > 0 ? g_count[3] - 1 : 0));
+ dmms2.erase(dmms2.begin(), dmms2.end());
+ check_expr(dmms2.size() == 0);
+ check_expr(dmms2.empty());
+
+ dmmsi = dmms1.begin();
+ dmmsi++;
+ dmmsi2 = dmmsi;
+ dmmsi2++;
+ dmmsi2++;
+ dmms2.insert(dmmsi, dmmsi2);// 2 recs inserted, [dmi, dmi2)
+ size_t sssz;
+ check_expr((sssz = dmms2.size()) == 2);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dmms1.swap(dmms2);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ size_t dmms1sz, dmms2sz;
+ check_expr((dmms1sz = dmms1.size()) == 2 && (dmms2sz = dmms2.size()) == sizet1 - 1);
+
+ dmms1.clear();
+ dmms2.clear();
+ dmms3.clear();
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+} // test_mset_member_functions
+
+void TestAssoc::test_char_star_string_storage()
+{
+ int i;
+ // testing varying length data element storage/retrieval
+ cout<<"\n_testing char*/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");
+// = _T("abc"), *cstr2 = _T("defcd"), *cstr3 = _T("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');// itis 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);
+
+ }
+
+} // test_char_star_string_storage
+
+void TestAssoc::test_fixed_len_obj_storage()
+{
+ int i;
+ map<int, sms_t> ssmsmap;
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ typedef db_map<int, sms_t> smsmap_t;
+ smsmap_t smsmap(dmdb6, penv);
+
+ sms_t smsmsg;
+ time_t now;
+ 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));
+ }
+ smsmap.clear();
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+} //test_var_len_obj_storage
+
+void TestAssoc::test_arbitray_sequence_storage()
+{
+ int i, j;
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ // storing arbitary sequence test .
+ cout<<endl<<"Testing 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];
+ prgb1 = rgbelem;// Can't use rgbsmap[i] here because container::operator[] is an temporary value.;
+ 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);
+ check_expr(memcmp(prgb1, prgb2 = srmitr->second,
+ sizeof(RGBB) * rgblen(srmitr->second)) == 0);
+ rmitr.refresh();
+ }
+
+ for (i = 0; i < 10; i++)
+ delete []rgbs[i];
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+} // test_arbitray_sequence_storage
+
+void TestAssoc::test_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<<"\n_testing bulk 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);
+
+
+} //test_bulk_retrieval_read
+
+void TestAssoc::test_nested_txns()
+{
+ int i;
+ size_t sizet1;
+
+ if (!EXPLICIT_TXN)
+ return;// nested txn tests can't be run if container not txnal
+
+ // nested transaction test
+ // 1. many external txns nested, no internal txn.
+
+ typedef db_map<char*, char*, ElementHolder<char*> > strstrmap_t;
+ DbTxn *txn1 = NULL, *txn2, *txn3;
+ char kstr[10], dstr[10];
+ std::map<int, string> kstrs;
+ int commit_or_abort = 0;
+ set<int> idxset;
+ char *keystr;
+
+ strstrmap_t smap(dbstrmap, penv);
+commit_abort:
+
+#define _DB_STL_TEST_SET_TXN_NAME(txn) \
+ txn->set_name(commit_or_abort == 0 ? #txn"_commit" : #txn"_abort")
+
+ txn1 = begin_txn(0, penv);
+ smap.clear();
+ //txn1->set_name(commit_or_abort == 0 ? "txn1_commit" : "txn1_abort");
+ _DB_STL_TEST_SET_TXN_NAME(txn1);
+ memset(kstr, 0, sizeof(kstr));
+ memset(dstr, 0, sizeof(dstr));
+ for (char cc = 'a'; cc <= 'z'; cc++) {
+ _snprintf(kstr, 10, "%c%c%c", cc, cc, cc);
+ for (int kk = 0; kk < 9; kk++)
+ dstr[kk] = cc;
+
+ i = cc - 'a';
+ kstrs.insert(make_pair(i, string(kstr)));
+ switch (i) {
+ case 3:
+ txn2 = begin_txn(0, penv);// nest txn2 into txn1
+ _DB_STL_TEST_SET_TXN_NAME(txn2);
+ break;
+ case 6://
+ abort_txn(penv); // abort txn2
+
+ for (int kk = 3; kk < 6; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ check_expr(smap.count(keystr) == 0);
+ }
+
+ txn2 = begin_txn(0, penv);// nest txn2 into txn1
+ _DB_STL_TEST_SET_TXN_NAME(txn2);
+ break;
+ case 9:// 6--11: txn3 abort and txn2 commit
+ txn3 = begin_txn(0, penv);// nest txn3 into txn2, txn2 is in txn1
+ _DB_STL_TEST_SET_TXN_NAME(txn3);
+ break;
+ case 12:
+ abort_txn(penv);// abort txn3
+ commit_txn(penv);// commit txn2, its txn3 part is not applied
+ for (int kk = 6; kk < 12; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ if (kk < 9)
+ check_expr((sizet1 = smap.count(keystr)) > 0);
+ if (kk >= 9)
+ check_expr(smap.count(keystr) == 0);
+ }
+
+ break;
+ case 15:// 15--18: txn3 commit and txn2 abort
+ txn2 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn2);
+ break;
+ case 17:
+ txn3 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn3);
+ break;
+ case 19:
+ commit_txn(penv);// commit txn3
+ abort_txn(penv);// abort txn2;
+ for (int kk = 15; kk < 19; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ check_expr(smap.count(keystr) == 0);
+ }
+ txn2 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn2);
+ break;
+ case 20:
+ txn3 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn3);
+ break;
+ case 22:
+ // txn3 is unresolved, after commit txn2, txn3 should have been commited
+ commit_txn(penv, txn2);
+ for (int kk = 19; kk < 22; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ check_expr(smap.count(keystr) > 0);
+ }
+ txn2 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn2);
+ break;
+ case 23:
+ txn3 = begin_txn(0, penv);
+ _DB_STL_TEST_SET_TXN_NAME(txn3);
+ break;
+ case 25:
+ // txn3 is unresolved, after abort txn2, txn3 should have been aborted
+ abort_txn(penv, txn2);
+ for (int kk = 22; kk < 24; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ check_expr(smap.count(keystr) == 0);
+ }
+
+ break;
+
+ default:
+ break;
+
+ }//switch
+
+ smap.insert(make_pair(kstr, dstr));
+ }// for
+
+ if (commit_or_abort == 0) {
+
+ // if txn1 commits, 0 1 2 6 7 8 12 13 14 19 20 21 25, 26
+ idxset.insert(0);
+ idxset.insert(1);
+ idxset.insert(2);
+ idxset.insert(6);
+ idxset.insert(7);
+ idxset.insert(8);
+ idxset.insert(12);
+ idxset.insert(13);
+ idxset.insert(14);
+ idxset.insert(19);
+ idxset.insert(20);
+ idxset.insert(21);
+ idxset.insert(25);
+
+
+
+ for (int kk = 0; kk < 26; kk++) {
+ keystr = const_cast<char*>(kstrs[kk].c_str());
+ sizet1 = smap.count(keystr);
+ if (idxset.count(kk) > 0) {
+ check_expr(sizet1 > 0);
+ } else {
+ check_expr(sizet1 == 0);
+ }
+ }
+
+ commit_or_abort = 1;
+ smap.clear();
+ commit_txn(penv, txn1);
+ goto commit_abort;
+ }
+
+ if (commit_or_abort != 0){
+ abort_txn(penv, txn1);// non could have been inserted
+ begin_txn(0, penv);// put this call in a txnal context
+ check_expr((sizet1 = smap.size()) == 0);
+ commit_txn(penv);
+ }
+
+ if (TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+
+ return;
+} // test_nested_txns
+
+
+// Testing miscellaneous functions.
+void TestAssoc::test_etc()
+{
+ set_global_dbfile_suffix_number(65536);
+ DbEnv *penvtmp = dbstl::open_env(".", 0, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL);
+ dbstl::close_db_env(penvtmp);
+ db_mutex_t mtxhdl = dbstl::alloc_mutex();
+ lock_mutex(mtxhdl);
+ unlock_mutex(mtxhdl);
+ free_mutex(mtxhdl);
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_DEADLOCK);
+ } catch (DbDeadlockException e1)
+ {}
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", DB_LOCK_NOTGRANTED);
+ } catch (DbLockNotGrantedException e2)
+ {}
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", DB_REP_HANDLE_DEAD);
+ } catch (DbRepHandleDeadException e13)
+ {}
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", DB_RUNRECOVERY);
+ } catch (DbRunRecoveryException e4)
+ {}
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", 12345);
+ } catch (DbException e1)
+ {}
+
+ try {
+ throw_bdb_exception("test_assoc::test_etc()", 54321);
+ } catch (DbException e1)
+ {}
+
+ ptint_vector vctr;
+ vctr.set_all_flags(1, 1, 1);
+ check_expr(vctr.get_commit_flags() == 1);
+ check_expr(vctr.get_cursor_open_flags() == 1);
+ check_expr(vctr.get_db_open_flags() & DB_CREATE);
+ check_expr(vctr.get_txn_begin_flags() == 1);
+ vctr.get_db_set_flags();
+ vctr.set_commit_flags(2);
+ check_expr(vctr.get_commit_flags() == 2);
+ vctr.set_cursor_open_flags(2);
+ check_expr(vctr.get_cursor_open_flags() == 2);
+ vctr.set_txn_begin_flags(2);
+ check_expr(vctr.get_txn_begin_flags() == 2);
+
+
+}
+
+
diff --git a/db-4.8.30/test_stl/base/test_dbstl.cpp b/db-4.8.30/test_stl/base/test_dbstl.cpp
new file mode 100644
index 0000000..0a75c72
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_dbstl.cpp
@@ -0,0 +1,313 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+// test_dbstl.cpp : A test program which tests all container's all methods,
+// by verify the result is identical to expected value, or by doing paralell
+// operations with corresponding container of STL and verify the result of
+// both containers are identical after the same operations. Also, it tests
+// multithreaded test
+//
+#include "db_config.h"
+#include "db_int.h"
+
+#include "test.h"
+#include "test_util.h"
+#include "test_vector.h"
+#include "test_assoc.h"
+#include "test_mt.h"
+
+int main(int argc, char *argv[])
+{
+ int c, i, j, ret;
+ int nreader = 5, nwriter = 3;
+ char *mode = NULL;
+ int flags = DB_THREAD, setflags = 0, EXPLICIT_TXN = 0;
+ int TEST_AUTOCOMMIT = 1, totalinsert = 100, verbose = 0;
+ DBTYPE dbtype = DB_BTREE;
+ int gi, shortest = 50, longest = 200, loop_count = 1;
+ bool multionly = false;
+ u_int32_t sflags = 0, oflags = 0;
+ u_int32_t cachesize = 8 * 1024 * 1024;
+ db_threadid_t tid;
+ string contname;
+ DbEnv *penv = NULL;
+ Db *dbstrv = NULL;
+ __os_id(0, 0, &tid);
+
+ TestParam *ptp = new TestParam;
+ ContainerType contypes[] = {
+ ct_vector,
+ ct_map,
+ ct_multimap,
+ ct_set,
+ ct_multiset,
+ ct_none
+ };
+
+ while ((c = getopt(argc, argv, "MT:c:hk:l:m:n:r:s:t:vw:")) != EOF) {
+ switch (c) {
+ case 'M':
+ multionly = true;
+ break;
+ case 'T':
+ totalinsert = atoi(optarg);
+ break;
+ case 'c':
+ cachesize = atoi(optarg);
+ break;
+ case 'h':
+ usage();
+ return 0;
+ break;
+ case 'k':
+ shortest = atoi(optarg);
+ break;
+ case 'l':
+ longest = atoi(optarg);
+ break;
+ case 'm':
+ mode = optarg;
+ break;
+ case 'n':
+ loop_count = atoi(optarg);
+ break;
+ case 'r':
+ nreader = atoi(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;
+ case 'w':
+ nwriter = atoi(optarg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (nwriter < 3)
+ nwriter = 3;
+
+ 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;
+ g_test_start_txn = TEST_AUTOCOMMIT * EXPLICIT_TXN;
+ ptp->EXPLICIT_TXN = EXPLICIT_TXN;
+ ptp->flags = flags;
+ ptp->dbtype = dbtype;
+ ptp->setflags = setflags;
+ ptp->TEST_AUTOCOMMIT = TEST_AUTOCOMMIT;
+ ptp->dboflags = DB_THREAD;
+
+ // This may fail because there is already dbenv.
+ __os_mkdir(NULL, "dbenv", 0777);
+ if (!multionly){
+ if (loop_count <= 0)
+ loop_count = 1;
+ dbstl_startup();
+ for (; loop_count > 0; loop_count--){
+ rmdir_rcsv("dbenv", true);
+ BDBOP(__os_mkdir(NULL, "dbenv/data", 0777), ret);// This should not fail.
+ penv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
+ BDBOP(penv->set_flags(setflags, 1), ret);
+ BDBOP(penv->set_cachesize(0, cachesize, 1), ret);
+ BDBOP(penv->set_data_dir("data"), 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);
+ penv->log_set_config(DB_LOG_IN_MEMORY, 1);
+ penv->set_lg_bsize(128 * 1024 * 1024);
+
+ BDBOP(penv->open("dbenv", flags | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0777), ret);
+ register_db_env(penv);
+ // CDS dose not need deadlock detection
+ if (penv->get_open_flags(&oflags) == 0 && ((oflags & DB_INIT_TXN) != 0)) {
+ penv->set_lk_detect(DB_LOCK_RANDOM);
+ penv->set_timeout(1000000, DB_SET_LOCK_TIMEOUT);
+
+ }
+
+ ptp->dbenv = penv;
+ g_env = penv;
+ TestVector testvector(ptp);
+ testvector.start_test();
+ TestAssoc testassoc(ptp);
+ testassoc.start_test();
+
+ close_all_dbs();
+ //close_db_env(penv);
+ close_all_db_envs();
+ cerr<<"\n\nOne round of dbstl test is run to completion successfully!\n\n";
+ }
+ }
+ else {
+ dbstl_startup();
+ rmdir_rcsv("dbenv", true);
+ BDBOP(__os_mkdir(NULL, "dbenv/data", 0777), ret);// This should not fail.
+ penv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
+ BDBOP(penv->set_flags(setflags, 1), ret);
+ BDBOP(penv->set_cachesize(0, cachesize, 1), ret);
+ BDBOP(penv->set_data_dir("data"), ret);
+
+ // Multi-CPU machines requires larger lockers/locks/objects because of
+ // the higher concurrency, more iterators can be opened at the same time.
+ // This setting was required by the stahp05 8-cpu machine, not others.
+ BDBOP(penv->set_lk_max_lockers(100000), ret);
+ BDBOP(penv->set_lk_max_locks(100000), ret);
+ BDBOP(penv->set_lk_max_objects(100000), ret);
+
+ penv->set_flags(DB_TXN_NOSYNC, 1);
+ penv->log_set_config(DB_LOG_IN_MEMORY, 1);
+ penv->set_lg_bsize(128 * 1024 * 1024);
+
+ BDBOP(penv->open("dbenv", flags | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0777), ret);
+ register_db_env(penv);
+ // CDS dose not need deadlock detection
+ if (penv->get_open_flags(&oflags) == 0 && ((oflags & DB_INIT_TXN) != 0)) {
+ penv->set_lk_detect(DB_LOCK_RANDOM);
+ penv->set_timeout(1000000, DB_SET_LOCK_TIMEOUT);
+ }
+
+ ptp->dbenv = penv;
+ g_env = penv;
+
+ ThreadMgr thrds, insthrds;
+ vector<wt_job> jobs;
+ jobs.push_back(wt_insert);
+ jobs.push_back(wt_update);
+ jobs.push_back(wt_delete);
+ srand ((unsigned int)tid);
+
+ for (i = 3; i < nwriter; i++) {
+ j = rand() % 3;
+ switch (j) {
+ case 0: jobs.push_back(wt_insert); break;
+ case 1: jobs.push_back(wt_update); break;
+ case 2: jobs.push_back(wt_delete); break;
+ }
+ }
+
+ vector<WorkerThread *> vctthrds;
+ WorkerThread *pwthrd;
+ for (gi = 0; contypes[gi] != ct_none; gi++) {
+
+ switch (contypes[gi]) {
+ case ct_vector: contname = "db_vector"; break;
+ case ct_map: contname = "db_map"; break;
+ case ct_multimap: contname = "db_multimap"; break;
+ case ct_set: contname = "db_set"; break;
+ case ct_multiset: contname = "db_multiset"; break;
+ default: throw "unexpected container type!"; break;
+ }
+ cout<<endl<<contname<<" multi-threaded tests:\n";
+
+ g_StopInsert = 0;
+ WorkerThread par;
+ memset(&par, 0, sizeof(par));
+ par.total_insert = totalinsert;
+ par.verbose = verbose != 0;
+ par.strlenmax = longest;
+ par.strlenmin = shortest;
+ par.cntnr_type = contypes[gi];
+ par.penv = penv;
+ if (par.cntnr_type != ct_vector) {
+ if (par.cntnr_type == ct_map ||
+ par.cntnr_type == ct_set)
+ sflags = 0;
+ else if (par.cntnr_type == ct_multimap ||
+ par.cntnr_type == ct_multiset)
+ sflags = DB_DUP;
+ par.pdb = dbstl::
+ open_db(penv, "db_mt_map.db",
+ ptp->dbtype, DB_CREATE | ptp->dboflags, sflags);
+ } else if (par.cntnr_type == ct_vector) {
+ if (NULL == dbstrv)
+ dbstrv = dbstl::open_db(penv, "dbstr.db",
+ DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER);
+ par.pdb = dbstrv;
+ }
+
+ par.txnal = ptp->EXPLICIT_TXN != 0;
+ for (j = 0; j < nwriter; j++) {
+ par.job = jobs[j];
+ pwthrd = new WorkerThread(par);
+ if (par.job == wt_insert) {
+ insthrds.create_thread(pwthrd);
+ } else {
+ thrds.create_thread(pwthrd);
+ }
+
+ vctthrds.push_back(pwthrd);
+ if (j == 0)
+ __os_yield(NULL, 3, 0);// sleep 3 secs
+ }
+
+ par.job = wt_read;
+ for (i = 0; i < nreader; i++) {
+ pwthrd = new WorkerThread(par);
+ thrds.create_thread(pwthrd);
+ vctthrds.push_back(pwthrd);
+ }
+
+ thrds.join_all();
+
+ g_StopInsert = 1;
+ insthrds.join_all();
+ for (vector<WorkerThread *>::size_type ui = 0; ui < vctthrds.size(); ui++)
+ delete vctthrds[ui];
+ vctthrds.clear();
+ if (ptp->EXPLICIT_TXN && !TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ dbstl::close_db(par.pdb);
+ penv->dbremove(dbstl::current_txn(penv), "db_mt_map.db", NULL, 0);
+ if (ptp->EXPLICIT_TXN && !TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+ thrds.clear();
+ insthrds.clear();
+ cout.flush();
+
+ } // for (int gi
+
+
+ } // else
+
+ delete ptp;
+ dbstl_exit();
+
+ if (penv)
+ delete penv;
+}
diff --git a/db-4.8.30/test_stl/base/test_mt.h b/db-4.8.30/test_stl/base/test_mt.h
new file mode 100644
index 0000000..ae4794b
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_mt.h
@@ -0,0 +1,914 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "test.h"
+
+// tests containers in multiple threads, this thread class
+// runs the thread function in specified manner---manipulating
+// a specified type of container, with some thread inserting,
+// updating, and deleting, some others reading specified amount
+// of key/data pairs.
+//
+class WorkerThread
+{
+public:
+ bool txnal/* if true, will create txn */, verbose;
+ wt_job job;
+ ContainerType cntnr_type;
+ int total_insert;
+ int strlenmin, strlenmax;
+ rand_str_dbt rand_str_maker;
+ Db *pdb;
+ DbEnv *penv;
+
+ WorkerThread()
+ {
+ pdb = NULL;
+ penv = NULL;
+
+ }
+
+ WorkerThread(const WorkerThread& wt)
+ {
+ memcpy(this, &wt, sizeof(wt));
+ }
+
+ void run()
+ {
+ WorkerThread *p = this;
+ db_threadid_t tid;
+ int cnt = 0, i, total = total_insert, ndx;
+ DbstlDbt dbt, dbt2;
+ string str, str2;
+ bool iscds = false;
+ u_int32_t oflags;
+ size_t dlcnt = 0;
+
+
+ dbt.set_flags(DB_DBT_USERMEM);
+ dbt.set_data(DbstlMalloc(strlenmax + 10));
+ dbt.set_ulen(strlenmax + 10);
+ dbt2.set_flags(DB_DBT_USERMEM);
+ dbt2.set_data(DbstlMalloc(strlenmax + 10));
+ dbt2.set_ulen(strlenmax + 10);
+
+ penv->get_open_flags(&oflags);
+ if (oflags & DB_INIT_CDB)
+ iscds = true;
+ __os_id(NULL, 0, &tid);
+ dbstl::register_db(p->pdb);
+ dbstl::register_db_env(penv);
+ if (p->cntnr_type == ct_vector) {
+ typedef db_vector<DbstlDbt> container_t;
+ container_t vi(p->pdb, penv);
+ const container_t& vi0 = vi;
+ srand((unsigned int)tid);
+ switch (p->job) {
+ case wt_read: {
+
+ while (cnt < total - 1) {
+ cnt = 0;
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::const_iterator itr = vi0.begin(); itr != vi0.end() && cnt < total - 1;
+ itr++, cnt++) {
+ str = (char*)((*itr).get_data());
+ if (verbose)
+ cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<"\t [ "<< itr.get_current_index()<<" ] = "<<str.c_str();
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 1, 0); // sleep 1 sec
+ }
+ if (iscds) // The update and delete thread will block until insert thread exits in cds mode
+ g_StopInsert = 1;
+ cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting, dead lock count = "<<dlcnt;
+ break;
+ } // case wt_job:
+
+ case wt_insert: {// writer
+
+ for (i = 0; g_StopInsert == 0; i++) {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ vi.push_back(dbt);
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ if (verbose)
+ cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str();
+ } catch (DbException e) {
+ i--;
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ }
+ cout<<"\n[ "<<tid<<" ] writer OK, exiting... dead lock count = "<<dlcnt;
+
+ break;
+
+ } // case wt_insert
+
+ case wt_delete: {
+ i = 0; // ADDITIVE, do total * 0.3 times of successful deletes, not necessarily delete so many recs because some ops may be aborted
+ while ( i < total * 0.1) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ while (i < total * 0.1) {
+ container_t::iterator itr = vi.begin();
+ itr += (ndx = rand() % total);
+ if (itr != vi.end()) {
+
+ vi.erase(itr);
+ i++;
+ if (verbose)
+ cout<<endl<<"vector element deleted: "<<itr.get_current_index()<<" : "<<(char*)(itr->get_data());
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ }
+ cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ }// case wt_delete
+
+ case wt_update: {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+ i = 0;// ADDITIVE
+
+ while ( i < total * 0.5) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ while (i < total * 0.5) {
+ container_t::iterator itr = vi.begin();
+ itr += (ndx = rand() % total);
+ if (itr != vi.end()) {
+ if (verbose)
+ cout<<endl<<"vector element updated: "<<itr.get_current_index()<<" updated: "<<(char*)(itr->get_data())<<" ===> ";
+ *itr = dbt;
+ i++;
+ if (verbose)
+ cout<<(char*)dbt.get_data();
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ }
+ cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt;
+ break;
+ }; // case wt_update
+
+ } // switch (p->job)
+ } // fi
+ if (p->cntnr_type == ct_map) {
+ typedef db_map<ptint , DbstlDbt> container_t;
+ container_t vi(p->pdb, penv);
+ const container_t& vi0 = vi;
+ container_t::iterator itr;
+ pair<container_t::iterator, bool> insret;
+ switch (p->job) {
+ case wt_read:
+ {
+ while (cnt < total - 1) {
+ cnt = 0;
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end();
+ itrc++, cnt++) {
+ //str = (char*)((*itrc).first.get_data());
+ str2 = (char*)((*itrc).second.get_data());
+ if (verbose)
+ cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<itrc->first<<"--> "<<str2.c_str();
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 1, 0); // sleep 1 sec
+ }
+ if (iscds) // The update and delete thread will block until insert thread exits in cds mode
+ g_StopInsert = 1;
+ cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt;
+ break;
+ }
+ case wt_insert:
+ {// writer
+
+tag6: for (i = 0; g_StopInsert == 0; i++) {
+ //rand_str_maker(dbt, str);
+ rand_str_maker(dbt2, str2, strlenmin, strlenmax);
+ if (i % 100 == 0)
+ __os_yield(NULL, 0, 0); // yield cpu
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ insret = vi.insert(make_pair(i, dbt2));
+ //if (insret.second == false) // fail to insert
+ // i--;
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ if (verbose)
+ cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str()<<" --> "<<str2.c_str();
+ } catch (DbException e) {
+ i--;
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ goto tag6; // continue;
+ }
+
+ }
+ cout<<"\n [ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt;
+ break;
+ } //case wt_insert:
+
+ case wt_delete:
+ {
+ i = 0;// ADDITIVE
+ while (i < total * 0.1) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (; i < total * 0.1;) {
+ itr = vi.begin();
+ itr.move_to((ndx = rand() % total));
+ if (itr != vi.end()) {
+ vi.erase(itr);
+ i++;
+ if (verbose)
+ cout<<endl<<"map k/d deleted: "<<itr->first<<" : "<<(char*)(itr->second.get_data());
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ }// case wt_delete
+
+ case wt_update:
+ {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+ i = 0;
+ while ( i < total * 0.5) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (i = 0; i < total * 0.5;) {// REAL DELETE: really update total * 0.5 number of recs from db
+ itr = vi.begin();
+ itr.move_to(ndx = rand() % total);
+ if (itr != vi.end()) {
+ if (verbose)
+ cout<<endl<<"map key = "<<itr->first<<" updated: "<<(char*)(itr->second.get_data())<<" ===> ";
+ itr->second = dbt;
+ i++;
+ if (verbose)
+ cout<<(char*)dbt.get_data();
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt;
+ break;
+ }; // case wt_update
+ } //switch (p->job)
+
+ }
+
+ if (p->cntnr_type == ct_multimap) {
+ typedef db_multimap<ptint , DbstlDbt> container_t;
+ container_t vi(p->pdb, penv);
+ const container_t& vi0 = vi;
+
+ switch (p->job) {
+ case wt_read:
+ {
+
+ while (cnt < total - 1) {
+ cnt = 0;
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end();
+ itrc++, cnt++) {
+ //str = (char*)((*itrc).first.get_data());
+ str2 = (char*)((*itrc).second.get_data());
+ if (verbose)
+ cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<itrc->first<<"--> "<<str2.c_str();
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 1, 0); // sleep 1 sec
+ }
+ if (iscds) // The update and delete thread will block until insert thread exits in cds mode
+ g_StopInsert = 1;
+ cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt;
+ break;
+ } //case wt_read:
+
+ case wt_insert:
+ {// writer
+ srand ((unsigned int)tid);
+ int j, dupcnt;
+ for (i = 0; g_StopInsert == 0; i += dupcnt) {
+ //rand_str_maker(dbt, str);
+ for (j = 0, dupcnt = (rand() % 5); j < dupcnt; j++) {
+
+ rand_str_maker(dbt2, str2, strlenmin, strlenmax);
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ vi.insert(make_pair(i, dbt2));
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ if (verbose)
+ cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str()<<" --> "<<str2.c_str();
+ } catch (DbException e) {
+ i--;
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ }
+ } // there may be more than total number of recs inserted because of the dupcnt
+ cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt;
+ break;
+ } //case wt_insert:
+
+ case wt_delete:
+ {
+ i = 0;// ADDITIVE
+ while ( i < total * 0.1) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::iterator itr = vi.begin(); i < total * 0.1;) {
+
+ itr.move_to(ndx = rand() % total);
+ if (itr != vi.end()) {
+
+ vi.erase(itr);
+ i++;
+ if (verbose)
+ cout<<endl<<"multimap k/d deleted: "<<itr->first<<" : "<<(char*)(itr->second.get_data());
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ }// case wt_delete
+
+ case wt_update:
+ {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+ i = 0;// ADDITIVE
+ while (i < total * 0.5) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::iterator itr = vi.begin(); i < total * 0.5;) {
+
+ itr.move_to(ndx = rand() % total);
+ if (itr != vi.end()) {
+ if (verbose)
+ cout<<endl<<"multimap key = "<<itr->first<<" updated: "<<(char*)(itr->second.get_data())<<" ===> ";
+ itr->second = dbt;
+ i++;
+ if (verbose)
+ cout<<(char*)dbt.get_data();
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+
+ }
+ cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ } // case wt_update
+ } // switch (p->job)
+ }
+
+ if (p->cntnr_type == ct_set) {
+ typedef db_set<DbstlDbt> container_t;
+ container_t vi(p->pdb, penv);
+ const container_t &vi0 = vi;
+ container_t::iterator itr;
+ int rowcnt;
+ int j;
+ switch (p->job) {
+ case wt_read:
+ {
+
+ while (cnt < total - 1) {
+ cnt = 0;
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end();
+ itrc++, cnt++) {
+ str = (char*)((*itrc).get_data());
+ if (verbose)
+ cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<str.c_str();
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 1, 0); // sleep 1 sec
+ }
+ if (iscds) // The update and delete thread will block until insert thread exits in cds mode
+ g_StopInsert = 1;
+ cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt;
+ break;
+ }
+ case wt_insert:
+ {// writer
+ srand ((unsigned int)tid);
+
+ pair<container_t::iterator, bool> insret;
+ for (i = 0; g_StopInsert == 0; i += 1) {
+
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ insret = vi.insert(dbt);
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ if (insret.second == false) // fail to insert
+ i--;
+ if (verbose)
+ cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str();
+ } catch (DbException e) {
+ i--;
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+
+ } // there may be more than total number of recs inserted because of the dupcnt
+ cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt;
+ break;
+ } // case wt_insert:
+
+ case wt_delete:
+ {
+ i = 0;
+ j = 0;
+ while (i < total * 0.1) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for ( ; i < total * 0.1;) {// ADDITIVE
+ rowcnt = rand() % total;
+ for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++)
+ ; // move to a random pos
+ if (itr != vi.end()) {
+
+ vi.erase(itr);
+ i++;
+ if (verbose)
+ cout<<endl<<"set key deleted: "<<(char*)(itr->get_data());
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ }// case wt_delete
+
+ case wt_update:
+ {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+ i = 0;
+ while ( i < total * 0.5) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (i = 0; i < total * 0.5;) { // REAL UPDATE
+ rowcnt = rand() % total;
+
+ for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++)
+ ; // move to a random pos
+ if (itr != vi.end()) {
+ if (verbose)
+ cout<<endl<<"set key updated: "<<(char*)(itr->get_data())<<" ===> ";
+ *itr = dbt;
+ i++;
+ if (verbose)
+ cout<<(char*)dbt.get_data();
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt;
+ break;
+ }// case wt_update
+ } // switch (p->job)
+ } // fi
+
+ if (p->cntnr_type == ct_multiset) {
+ typedef db_multiset<DbstlDbt> container_t;
+ container_t::iterator itr;
+ int rowcnt;
+ int j, dupcnt;
+ container_t vi(p->pdb, penv);
+ const container_t &vi0 = vi;
+ switch (p->job) {
+ case wt_read:
+ {
+
+ while (cnt < total - 1) {
+ cnt = 0;
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (container_t::const_iterator itrc = vi0.begin(); itrc != vi0.end();
+ itrc++, cnt++) {
+ str = (char*)((*itrc).get_data());
+ if (verbose)
+ cout<<"\n [ "<<cnt<<" ] tid: "<<tid<<'\t'<<str.c_str();
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 1, 0); // sleep 1 sec
+ }
+ if (iscds) // The update and delete thread will block until insert thread exits in cds mode
+ g_StopInsert = 1;
+ cout<<"\nthread "<<tid<<" got enough key/data pairs now, exiting... dead lock count = "<<dlcnt;
+ break;
+ } // case wt_read:
+ case wt_insert:
+ {// writer
+ srand ((unsigned int)tid);
+
+ for (i = 0; g_StopInsert == 0; i += dupcnt) {
+
+ for (j = 0, dupcnt = (rand() % 5); j < dupcnt; j++) {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ vi.insert(dbt);
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ if (verbose)
+ cout<<endl<<"[ "<<i<<" ] thread "<<tid<<" put a string "<<str.c_str();
+ } catch (DbException e) {
+ i--;
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ }
+ } // there may be more than total number of recs inserted because of the dupcnt
+ cout<<"\n[ "<<tid<<" ] writer thread finishes writing, exiting... dead lock count = "<<dlcnt;
+ break;
+ } // case wt_insert:
+ case wt_delete:
+ {
+ i = 0;
+ j = 0;
+ while (i < total * 0.1) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (; i < total * 0.1;) {// ADDITIVE
+ rowcnt = rand() % total;
+ for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++)
+ ; // move to a random pos
+ if (itr != vi.end()) {
+
+ vi.erase(itr);
+ i++;
+ if (verbose)
+ cout<<endl<<"multiset key deleted: "<<(char*)(itr->get_data());
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] deleter OK, exiting... dead lock count = "<<dlcnt;
+ break;
+
+ }// case wt_delete
+
+ case wt_update:
+ {
+ rand_str_maker(dbt, str, strlenmin, strlenmax);
+ i = 0;
+ while ( i < total * 0.5) {
+
+ try {
+ if (p->txnal)
+ dbstl::begin_txn(0, penv);
+ for (i = 0; i < total * 0.5;) {// REAL UPDATE
+ rowcnt = rand() % total;
+ for (itr = vi.begin(), j = 0; j < rowcnt; j++, itr++)
+ ; // move to a random pos
+ if (itr != vi.end()) {
+ if (verbose)
+ cout<<endl<<"multiset key updated: "<<(char*)(itr->get_data())<<" ===> ";
+ *itr = dbt;
+ i++;
+ if (verbose)
+ cout<<(char*)dbt.get_data();
+
+ } else {
+ if (vi.size() == 0)
+ return;
+ __os_yield(NULL, 0, 500000);
+ }
+ }
+ if (p->txnal)
+ dbstl::commit_txn(penv);
+ } catch (DbException e) {
+ dlcnt++;
+ dbstl::abort_txn(penv);
+ if (e.get_errno() != DB_LOCK_DEADLOCK)
+ throw e;
+ else
+ continue;
+ }
+
+ __os_yield(NULL, 0, 500000);
+ }
+ cout<<"\n[ "<<tid<<" ] updater OK, exiting... dead lock count = "<<dlcnt;
+ break;
+ } // case wt_update
+ } //switch (p->job)
+ }// fi
+
+ }// void operator()()
+}; // WorkerThread
+
+// Used in the multi-threaded test to manage test threads,
+// works like boost::thread_group
+class ThreadMgr
+{
+public:
+ os_thread_t create_thread(WorkerThread *thrd);
+ void clear() { threads.clear();}
+ void join_all();
+ ThreadMgr() : threads(0){}
+private:
+ vector<os_thread_t> threads;
+}; // ThreadMgr
+
+#ifdef WIN32
+#define ThrdFuncRet DWORD
+#define FunctRet return (0)
+#else
+#define ThrdFuncRet void*
+#define FunctRet return (NULL)
+#endif
+
+static ThrdFuncRet thread_func(void *arg)
+{
+ (*((WorkerThread *)arg)).run();
+ FunctRet;
+}
+
+os_thread_t ThreadMgr::create_thread(WorkerThread *thrd)
+{
+ os_thread_t thrdhandle;
+
+ os_thread_create(&thrdhandle, NULL, thread_func, thrd);
+ threads.push_back(thrdhandle);
+ return thrdhandle;
+}
+
+void ThreadMgr::join_all()
+{
+ ThrdFuncRet ret;
+
+ for (size_t i = 0; i < threads.size(); i++)
+ os_thread_join(threads[i], &ret);
+}
diff --git a/db-4.8.30/test_stl/base/test_util.cpp b/db-4.8.30/test_stl/base/test_util.cpp
new file mode 100644
index 0000000..203d25b
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_util.cpp
@@ -0,0 +1,280 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "test.h"
+
+char rand_str_dbt::buf[rand_str_dbt::BUFLEN];
+bool rand_str_dbt::init = false;
+//boost::mutex g_mtx_co;// global mutex to sync create/open
+DbEnv *g_env = NULL;
+int g_test_start_txn = 0;
+int g_StopInsert = 0;
+
+bool strlt0(const char *s1, const char *s2)
+{
+ return strcmp(s1, s2) < 0;
+}
+
+bool streq0(const char *s1, const char *s2)// for list::unique
+{
+ return strcmp(s1, s2) == 0;
+}
+
+bool strlt(const string&s1, const string&s2)// for list::merge and list::sort
+{
+ return strcmp(s1.c_str(), s2.c_str()) < 0;
+}
+
+bool streq(const string&s1, const string&s2)// for list::unique
+{
+ return strcmp(s1.c_str(), s2.c_str()) == 0;
+}
+
+bool operator==(ElementHolder<const char *>s1, const char *s2)
+{
+ return strcmp(s1, s2) == 0;
+}
+
+bool operator==(ElementHolder<const wchar_t *>s1, const wchar_t *s2)
+{
+ return wcscmp(s1, s2) == 0;
+}
+
+bool operator!=(ElementHolder<const char *>s1, const char *s2)
+{
+ return !operator==(s1, s2);
+}
+
+bool operator!=(ElementHolder<const wchar_t *>s1, const wchar_t *s2)
+{
+ return !operator==(s1, s2);
+}
+
+size_t g_sum(size_t s, size_t e)
+{
+ size_t sum = 0;
+
+ for (size_t i = s; i <= e; i++)
+ sum += g_count[i];
+ return sum;
+}
+
+bool is_odd(ptint s)
+{
+ return ( s % 2) != 0;
+}
+
+ptint addup(const ptint&i, const ptint&j)
+{
+ return i + j;
+}
+
+ptint randint()
+{
+ return -999;
+}
+
+int randpos(int p)
+{
+ return abs(rand()) % p;
+}
+
+bool is2digits(ptint i)
+{
+ return (i > (9)) && (i < (100));
+}
+
+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 usage()
+{
+ cout<<
+ "\nusage: test_dbstl \n\
+[-M run multi-thread test only]\n\
+[-T number total number of insert in multithread test]\n\
+[-c number cache size]\n\
+[-h print this help message then exit]\n\
+[-k number shortest string inserted]\n\
+[-l number longest string inserted]\n\
+[-m ds/cds/tds use ds/cds/tds product]\n\
+[-r number number of reader threads in multithread test]\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\
+[-w number number of writer threads 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');
+}
+
+void copy_array(TCHAR**arr, TCHAR***dest)
+{
+ int i;
+
+ *dest = new TCHAR*[32];
+ for (i = 0; arr[i] != NULL; i++) {
+ (*dest)[i] = new TCHAR[_tcslen(arr[i])];
+ _tcscpy((*dest)[i], arr[i]);
+ }
+
+}
+
+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);
+}
+
+bool ptintless(const ptint& a, const ptint& b)
+{
+ return a < b;
+}
+
+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 mem
+// 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.
+
+ return;
+}
+
+// Create test directory.
+inline int dir_setup(const char *testdir)
+{
+ int ret;
+
+#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 3
+ if ((ret = __os_mkdir(NULL, testdir, 0755)) != 0) {
+#else
+ if ((ret = mkdir(testdir, 0755)) != 0) {
+#endif
+ fprintf(stderr,
+ "dir_setup: Creating directory %s: %s\n",
+ testdir, db_strerror(ret));
+ return (1);
+ }
+ return (0);
+}
+
+inline int os_unlink(const char *path)
+{
+#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 7
+ return (__os_unlink(NULL, path));
+#else
+ return (__os_unlink(NULL, path, 0));
+#endif
+}
+
+#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 4
+#define OS_EXISTS(a, b, c) __os_exists(a, b, c)
+#else
+#define OS_EXISTS(a, b, c) __os_exists(b, c)
+#endif
+
+// Remove contents in specified directory recursively(in DB versions earlier
+// than 4.6, don't recursively), and optionally remove the directory itself.
+int rmdir_rcsv(const char *dir, bool keep_this_dir)
+{
+ int cnt, i, isdir, ret;
+ char buf[1024], **names;
+
+ ret = 0;
+
+ /* If the directory doesn't exist, we're done. */
+ if (OS_EXISTS(NULL, dir, &isdir) != 0)
+ return (0);
+
+ /* Get a list of the directory contents. */
+#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
+ if ((ret = __os_dirlist(NULL, dir, 1, &names, &cnt)) != 0)
+ return (ret);
+#else
+ if ((ret = __os_dirlist(NULL, dir, &names, &cnt)) != 0)
+ return (ret);
+#endif
+ /* Go through the file name list, remove each file in the list */
+ for (i = 0; i < cnt; ++i) {
+ (void)snprintf(buf, sizeof(buf),
+ "%s%c%s", dir, PATH_SEPARATOR[0], names[i]);
+ if ((ret = OS_EXISTS(NULL, buf, &isdir)) != 0)
+ goto file_err;
+ if (!isdir && (ret = os_unlink(buf)) != 0) {
+file_err: fprintf(stderr,
+ "os_unlink: Error unlinking file: %s: %s\n",
+ buf, db_strerror(ret));
+ break;
+ }
+ if (isdir && rmdir_rcsv(buf, false) != 0)
+ goto file_err;
+ }
+
+ __os_dirfree(NULL, names, cnt);
+
+ /*
+ * If we removed the contents of the directory and we don't want to
+ * keep this directory, remove the directory itself.
+ */
+ if (i == cnt && !keep_this_dir && (ret = rmdir(dir)) != 0)
+ fprintf(stderr,
+ "rmdir_rcsv(%s): %s\n", dir, db_strerror(errno));
+ return (ret);
+} // rmdir_rcsv
+
diff --git a/db-4.8.30/test_stl/base/test_util.h b/db-4.8.30/test_stl/base/test_util.h
new file mode 100644
index 0000000..ca0fc87
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_util.h
@@ -0,0 +1,605 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "test.h"
+#include "ptype.h"
+
+/*
+ * this function should not be included into dbstl because swapping
+ * different type of vars is possible to lose precision, this is why std::swap
+ * requires same type. here I know I won't lose precision so I do it at my
+ * cost
+ */
+namespace std {
+template <Typename T1, Typename T2>
+void swap(T1&t1, T2&t2)
+{
+ T2 t;
+ t = t2;
+ t2 = t1;
+ t1 = t;
+
+}
+
+bool operator==(const pair<ptint, ElementHolder<ptint> >&v1, const pair<ptint, ElementHolder<ptint> >&v2)
+{
+ return v1.first == v2.first && v1.second._DB_STL_value() == v2.second._DB_STL_value();
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+bool operator==(const pair<T1, T2>&v1, const pair<T3, T4> &v2)
+{
+ return v1.first == v2.first && v1.second == v2.second;
+}
+} // namespace std
+
+template <Typename T1, Typename T2, Typename T3, Typename T4>
+bool is_equal(db_map<T1, T2, ElementHolder<T2> >& dv, map<T3, T4>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ typename db_map<T1, T2, ElementHolder<T2> >::iterator itr1;
+ typename map<T3, T4>::iterator itr2;
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())){
+ ret = false;
+ goto done;
+ }
+
+ for (itr1 = dv.begin(), itr2 = v.begin(); itr1 != dv.end(); ++itr1, ++itr2) {
+ if (itr1->first != itr2->first || itr1->second != itr2->second){
+ ret = false;
+ goto done;
+ }
+
+ }
+
+ ret = true;
+done:
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+
+}
+
+template <Typename T1, Typename T2, Typename T3, Typename T4>
+bool is_equal(db_map<T1, T2, ElementRef<T2> >& dv, map<T3, T4>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ typename db_map<T1, T2, ElementRef<T2> >::iterator itr1;
+ typename map<T3, T4>::iterator itr2;
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())){
+
+ ret = false;
+ goto done;
+ }
+
+
+ for (itr1 = dv.begin(), itr2 = v.begin(); itr1 != dv.end(); ++itr1, ++itr2) {
+ if (itr1->first != itr2->first || itr1->second != itr2->second){
+ ret = false;
+ goto done;
+ }
+ }
+
+ ret = true;
+done:
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+
+}
+
+
+template<Typename T1, Typename T2>
+bool is_equal(const db_set<T1, ElementHolder<T1> >&s1, const set<T2>&s2)
+{
+ bool ret;
+ typename db_set<T1, ElementHolder<T1> >::iterator itr;
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if (s1.size() != s2.size()){
+ ret = false;
+ goto done;
+ }
+
+ for (itr = s1.begin(); itr != s1.end(); itr++) {
+ if (s2.count(*itr) == 0) {
+ ret = false;
+ goto done;
+ }
+ }
+ ret = true;
+done:
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+
+}
+
+
+template <Typename T1, Typename T2>
+bool is_equal(const db_vector<T1>& dv, const vector<T2>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ T1 t1;
+ size_t i, sz = v.size();
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())) {
+ ret = false;
+ goto done;
+ }
+
+
+ for (i = 0; i < sz; i++) {
+ t1 = T1(dv[(index_type)i] );
+ if (t1 != v[i]){
+ ret = false;
+ goto done;
+ }
+ }
+ ret = true;
+done:
+
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+}
+
+// The following four functions are designed to work with is_equal to compare
+// char*/wchar_t* strings properly, unforturnately they can not override
+// the default pointer value comparison behavior.
+bool operator==(ElementHolder<const char *>s1, const char *s2);
+bool operator==(ElementHolder<const wchar_t *>s1, const wchar_t *s2);
+bool operator!=(ElementHolder<const char *>s1, const char *s2);
+bool operator!=(ElementHolder<const wchar_t *>s1, const wchar_t *s2);
+
+template <Typename T1>
+bool is_equal(const db_vector<T1, ElementHolder<T1> >& dv, const vector<T1>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ size_t i, sz = v.size();
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())) {
+ ret = false;
+ goto done;
+ }
+
+ for (i = 0; i < sz; i++) {
+ if (dv[(index_type)i] != v[i]) {
+ ret = false;
+ goto done;
+ }
+ }
+ ret = true;
+done:
+
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+}
+
+
+template <Typename T1, Typename T2>
+bool is_equal(db_vector<T1>& dv, list<T2>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ typename db_vector<T1>::iterator itr;
+ typename list<T2>::iterator itr2;
+
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())) {
+ ret = false;
+ goto done;
+ }
+
+
+ for (itr = dv.begin(), itr2 = v.begin();
+ itr2 != v.end(); ++itr, ++itr2) {
+ if (*itr != *itr2) {
+ ret = false;
+ goto done;
+ }
+ }
+ ret = true;
+done:
+
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+}
+
+bool is_equal(db_vector<char *, ElementHolder<char *> >&v1, std::list<string> &v2)
+{
+ db_vector<char *, ElementHolder<char *> >::iterator itr;
+ std::list<string>::iterator itr2;
+
+ if (v1.size() != v2.size())
+ return false;
+
+ for (itr = v1.begin(), itr2 = v2.begin(); itr2 != v2.end(); ++itr, ++itr2)
+ if (strcmp(*itr, (*itr2).c_str()) != 0)
+ return false;
+
+ return true;
+}
+
+template <Typename T1>
+class atom_equal {
+public:
+ bool operator()(T1 a, T1 b)
+ {
+ return a == b;
+ }
+};
+template<>
+class atom_equal<const char *> {
+public:
+ bool operator()(const char *s1, const char *s2)
+ {
+ return strcmp(s1, s2) == 0;
+ }
+};
+
+template <Typename T1>
+bool is_equal(const db_vector<T1, ElementHolder<T1> >& dv, const list<T1>&v)
+{
+ size_t s1, s2;
+ bool ret;
+ typename db_vector<T1, ElementHolder<T1> >::const_iterator itr;
+ typename list<T1>::const_iterator itr2;
+ atom_equal<T1> eqcmp;
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ if ((s1 = dv.size()) != (s2 = v.size())) {
+ ret = false;
+ goto done;
+ }
+
+
+ for (itr = dv.begin(), itr2 = v.begin();
+ itr2 != v.end(); ++itr, ++itr2) {
+ if (!eqcmp(*itr, *itr2)) {
+ ret = false;
+ goto done;
+ }
+ }
+ ret = true;
+done:
+
+ if (g_test_start_txn)
+ commit_txn(g_env);
+ return ret;
+}
+
+// fill the two vectors with identical n integers,starting from start
+template<Typename T>
+void fill(db_vector<ptype<T> >&v, vector<T>&sv, T start = 0, int n = 5)
+{
+ T i;
+
+ v.clear();
+ sv.clear();
+ for (i = start; i < n + start; i++) {
+ v.push_back(i);
+ sv.push_back(i);
+ }
+}
+
+
+template<Typename T>
+void fill(db_vector<T, ElementHolder<T> >&v, vector<T>&sv, T start = 0, int n = 5 )
+{
+ int i;
+
+ v.clear();
+ sv.clear();
+ for (i = 0; i < n; i++) {
+ v.push_back(i + start);
+ sv.push_back(i + start);
+ }
+}
+
+template <Typename T>
+void fill(db_map<ptype<T>, ptype<T> >&m, map<T, T>&sm,
+ T start = 0, int n = 5)
+{
+ int i;
+ ptype<T> pi;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ pi = i + start;
+ m.insert(make_pair(pi, pi));
+ sm.insert(make_pair(pi.v, pi.v));
+ }
+
+}
+
+
+template <Typename T>
+void fill(db_map<T, T, ElementHolder<T> >&m, map<T, T>&sm,
+ T start = 0, int n = 5)
+{
+ int i;
+ T pi;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ pi = i + start;
+ m.insert(make_pair(pi, pi));
+ sm.insert(make_pair(pi, pi));
+ }
+
+}
+
+
+template <Typename T>
+void fill(db_set<ptype<T> >&m, set<T>&sm, T start = 0, int n = 5)
+{
+ int i;
+ ptype<T> pi;
+
+ m.clear();
+ sm.clear();
+
+ for (i = 0; i < n; i++) {
+
+ pi = i + start;
+ m.insert(pi);
+ sm.insert(pi.v);
+ }
+
+}
+
+
+template <Typename T>
+void fill(db_set<T, ElementHolder<T> >&m, set<T>&sm,
+ T start = 0, int n = 5)
+{
+ int i;
+ T pi;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ pi = i + start;
+ m.insert(pi);
+ sm.insert(pi);
+ }
+
+}
+
+
+size_t g_count[256];
+template <Typename T>
+void fill(db_multimap<ptype<T>, ptype<T> >&m, multimap<T, T>&sm,
+ T start = 0, int n = 5, size_t randn = 5)
+{
+
+ int i;
+ size_t j, cnt;
+
+ if (randn == 0)
+ randn = 1;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ if (randn > 1)
+ cnt = abs(rand()) % randn;
+ if (cnt == 0)
+ cnt = randn;
+ i += start;
+ g_count[i] = cnt;
+ for (j = 0; j < cnt; j++) {// insert duplicates
+ m.insert(make_pair(i, ptype<T>(i)));
+ sm.insert(make_pair(i, i));
+ }
+ i -= start;
+ }
+}
+
+
+template <Typename T>
+void fill(db_multimap<T, T, ElementHolder<T> >&m, multimap<T, T>&sm,
+ T start = 0, int n = 5, size_t randn = 5)
+{
+ int i;
+ size_t j, cnt = 0;
+
+ if (randn < 5)
+ randn = 5;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ cnt = abs(rand()) % randn;
+ if (cnt == 0)
+ cnt = randn;
+ i += start;
+ g_count[i] = cnt;
+ for (j = 0; j < cnt; j++) {// insert duplicates
+ m.insert(make_pair(i, i));
+ sm.insert(make_pair(i, i));
+ }
+ i -= start;
+ }
+
+}
+
+
+template <Typename T>
+void fill(db_multiset<ptype<T> >&m, multiset<T>&sm, T start,
+ int n, size_t randn)
+{
+
+ int i;
+ size_t j, cnt;
+
+ if (randn == 0)
+ randn = 1;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ if (randn > 1)
+ cnt = abs(rand()) % randn;
+ if (cnt == 0)
+ cnt = randn;
+ i += start;
+ g_count[i] = cnt;
+ for (j = 0; j < cnt; j++) {// insert duplicates
+ m.insert(ptype<T>(i));
+ sm.insert(i);
+ }
+ i -= start;
+ }
+}
+
+
+template <Typename T>
+void fill(db_multiset<T, ElementHolder<T> >&m, multiset<T>&sm,
+ T start = 0, int n = 5 , size_t randn = 5)
+{
+ int i;
+ size_t j, cnt;
+
+ if (randn < 5)
+ randn = 5;
+
+ m.clear();
+ sm.clear();
+ for (i = 0; i < n; i++) {
+ cnt = abs(rand()) % randn;
+ if (cnt == 0)
+ cnt = randn;
+ i += start;
+ g_count[i] = cnt;
+ for (j = 0; j < cnt; j++) {// insert duplicates
+ m.insert(i);
+ sm.insert(i);
+ }
+ i -= start;
+ }
+}
+
+
+#ifdef TEST_PRIMITIVE
+bool is_odd_pair(pair<ptint, ElementHolder<ptint> >& s)
+{
+ return ( s.second._DB_STL_value() % 2) != 0;
+}
+#else
+bool is_odd_pair(pair<ptint, ElementRef<ptint> >& s)
+{
+ return ( s.second._DB_STL_value() % 2) != 0;
+}
+#endif
+
+
+template<Typename pair_type>
+void square_pair(pair_type&s)
+{
+ cout<<s.second*s.second<<'\t';
+}
+
+template<Typename pair_type>
+void square_pair2(pair_type&s)
+{
+ cout<<s.second*s.second<<'\t';
+}
+
+
+
+
+#ifndef TEST_PRIMITIVE
+bool is2digits_pair(pair<ptint, ElementRef<ptint> >& i)
+{
+ return (i.second._DB_STL_value() > (9)) && (i.second._DB_STL_value() < (100));
+}
+
+#else
+bool is2digits_pair(pair<ptint, ElementHolder<ptint> >& i)
+{
+ return (i.second._DB_STL_value() > (9)) && (i.second._DB_STL_value() < (100));
+}
+#endif
+bool is7(const ptint& value) { return (value == (ptint)7); }
+
+
+template <Typename T, Typename value_type_sub>
+void pprint(db_vector<T, value_type_sub>&v, const char *prefix = NULL)
+{
+return;
+ size_t i;
+ size_t sz = v.size();
+
+ cout<<"\n";
+ if (prefix)
+ cout<<prefix;
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ for (i = 0; i < sz; i++) {
+ cout<<"\t"<<(v[(index_type)i]);
+ }
+ if (g_test_start_txn)
+ commit_txn(g_env);
+}
+
+
+template <Typename T, Typename ddt, Typename value_type_sub>
+void pprint(db_map<T, ddt, value_type_sub>&v, const char *prefix = NULL)
+{
+return;
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ cout<<"\n";
+ if (prefix)
+ cout<<prefix;
+ typename db_map<T, ddt, value_type_sub>::iterator itr;
+ for (itr = v.begin(); itr != v.end(); itr++)
+ cout<<'\t'<<itr->first<<'\t'<<itr->second;
+ if (g_test_start_txn)
+ commit_txn(g_env);
+}
+
+
+template <Typename T, Typename value_type_sub>
+void pprint(db_set<T, value_type_sub>&v, const char *prefix = NULL)
+{
+return;
+ if (g_test_start_txn)
+ begin_txn(0, g_env);
+ cout<<"\n";
+ if (prefix)
+ cout<<prefix;
+ typename db_set<T, value_type_sub>::iterator itr;
+ for (itr = v.begin(); itr != v.end(); itr++)
+ cout<<'\t'<<*itr;
+ if (g_test_start_txn)
+ commit_txn(g_env);
+}
+
diff --git a/db-4.8.30/test_stl/base/test_vector.h b/db-4.8.30/test_stl/base/test_vector.h
new file mode 100644
index 0000000..efcf165
--- /dev/null
+++ b/db-4.8.30/test_stl/base/test_vector.h
@@ -0,0 +1,1338 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "test.h"
+
+#include <list>
+
+using std::list;
+using std::priority_queue;
+
+// This class tests all methods of db_vector and db_vector_iterator
+// Most tests are done by doing identical operations to db_vector
+// and std::vector and check the result data set in the two vectors
+// are identical. Also, almost all algorithms in std are applied to
+// the different ranges created from db_vector and std::vector, and
+// also compare result of the in the same way.
+//
+class TestVector
+{
+public:
+ ~TestVector();
+ TestVector(void *param1);
+ void start_test()
+ {
+
+ tb.begin("db_vector");
+ // Do not change the order of these functions.
+
+ // Test each member function of db_vector and
+ // db_vector_iterator that are shared by all three
+ // std containers std::vector, std::deque and std::list.
+ test_member_functions();
+
+ // Test std::list specific methods.
+ test_list_specific_member_functions();
+
+ // Use std functions to manipulate db_vector containers.
+ test_std_functions();
+
+ // Test storing primitive data.
+ test_primitive();
+
+ // Test whether db_vector works with std container adapters
+ // std::stack, std::queue and std::priority_queue
+ test_queue_stack();
+ tb.end();
+ }
+
+ void test_member_functions();
+ void test_list_specific_member_functions();
+ void test_std_functions();
+ void test_primitive();
+ void test_queue_stack();
+private:
+
+ int n;
+ int flags, setflags, EXPLICIT_TXN, TEST_AUTOCOMMIT;
+ DBTYPE dbtype;
+ DbEnv *penv;
+ Db *db, *db2, *db3;
+ Db *quedb, *pquedb;
+ test_block tb;
+
+ vector<int> svi, svi2, svi3;
+
+};
+
+TestVector::~TestVector()
+{
+
+}
+
+TestVector::TestVector(void *param1)
+{
+ check_expr(param1 != NULL);
+ TestParam *param = (TestParam*)param1;
+ TestParam *ptp = param;
+ penv = param->dbenv;
+ db = db2 = db3 = NULL;
+ flags = 0, setflags = 0, EXPLICIT_TXN = 1, TEST_AUTOCOMMIT = 0;
+ flags = param->flags;
+ dbtype = param->dbtype;
+ setflags = param->setflags;
+ TEST_AUTOCOMMIT = param->TEST_AUTOCOMMIT;
+ EXPLICIT_TXN = param->EXPLICIT_TXN;
+ n = 5;
+ dbtype = DB_BTREE;
+ db = dbstl::open_db(penv, "db1.db",
+ DB_RECNO, DB_CREATE | ptp->dboflags | DB_THREAD, DB_RENUMBER);
+ db2 = dbstl::open_db(penv, "db2.db",
+ DB_RECNO, DB_CREATE | ptp->dboflags, DB_RENUMBER);
+ 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);
+}
+
+void TestVector::test_member_functions()
+{
+ int i;
+ ptint_vector::iterator itr1, itr;
+ ptint_vector::reverse_iterator ritr1, ritr;
+ vector<int>::iterator sitr, sitr1;
+ vector<int>::reverse_iterator rsitr, rsitr1;
+
+
+ ptint_vector vi(db, penv);
+ const ptint_vector& cnstvi = vi;
+ vi.clear();
+ if ( EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ fill(vi, svi, 0, n);
+
+ for (i = 0; i < n; i++) {
+ ptint_vector::const_iterator citr, citr1;
+ citr = vi.begin() + i;
+ check_expr(*citr == vi[i]);
+ itr = citr;
+ check_expr(*citr == *itr);
+ *itr = i * 2 + 1;
+ citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == vi[i]);
+ }
+
+ for (i = 0; i < n; i++) {
+ ptint_vector::const_iterator citr = vi.begin() + i;
+ check_expr(*citr == vi[i]);
+ itr = citr;
+ check_expr(*citr == *itr);
+ *itr = i * 2 + 1;
+ ptint_vector::const_iterator citr1 = itr;
+ check_expr(*citr == *itr);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == vi[i]);
+ }
+
+ for (i = 0; i < n; i++) {
+ ptint_vector::iterator ncitr, ncitr1;
+ ptint_vector::const_iterator citr, citr1;
+
+ ncitr = cnstvi.begin() + i;
+ check_expr(*ncitr == cnstvi[i]);
+ citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*ncitr = i * 2 + 1;
+ citr1 = ncitr;
+ ncitr1 = citr1;
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == cnstvi[i]);
+ }
+
+ for (i = 0; i < n; i++) {
+
+ ptint_vector::iterator ncitr = cnstvi.begin() + i;
+ check_expr(*ncitr == cnstvi[i]);
+ ptint_vector::const_iterator citr = ncitr;
+ check_expr(*citr == *ncitr);
+ //*itr = i * 2 + 1;
+ ptint_vector::const_iterator citr1 = ncitr;
+ ptint_vector::iterator ncitr1 = citr1;
+
+ check_expr(*citr == *ncitr);
+ check_expr(*citr == *ncitr1);
+ check_expr(*citr == *citr1);
+ check_expr(*citr == cnstvi[i]);
+ }
+
+ {
+ vi.clear();
+ svi.clear();
+ vi.push_back(123);
+ svi.push_back(123);
+ ptint_vector::iterator ncitr = vi.begin();
+ vector<int>::iterator ncsitr = svi.begin();
+ *ncitr += 5;
+ *ncitr -= 3;
+ *ncitr *= 4;
+ *ncitr /= 2;
+ *ncitr %= 97;
+ (*ncitr)++;
+ (*ncitr)--;
+ ++(*ncitr);
+ --(*ncitr);
+ *ncsitr += 5;
+ *ncsitr -= 3;
+ *ncsitr *= 4;
+ *ncsitr /= 2;
+ *ncsitr %= 97;
+ (*ncsitr)++;
+ (*ncsitr)--;
+ ++(*ncsitr);
+ --(*ncsitr);
+ check_expr(*ncsitr == *ncitr);
+
+ *ncitr &= 0x9874abcd;
+ *ncitr |= 0x12345678;
+ *ncitr ^= 0x11223344;
+ *ncsitr &= 0x9874abcd;
+ *ncsitr |= 0x12345678;
+ *ncsitr ^= 0x11223344;
+ ncitr.refresh(true);
+ check_expr(*ncsitr == *ncitr);
+
+ vi.clear();
+ svi.clear();
+ db_vector<ptype<int> > tmpvi;
+ const db_vector<ptype<int> > & ctmpvi = tmpvi;
+ fill(tmpvi, svi, 0, n);
+ db_vector<ptype<int> >::const_reverse_iterator critr;
+ vector<int>::const_reverse_iterator crsitr;
+ db_vector<ptype<int> >::const_iterator citr2;
+ vector<int>::const_iterator csitr2;
+
+ check_expr(ctmpvi.back() == svi.back());
+ check_expr(ctmpvi.at(0) == svi.at(0));
+ critr = tmpvi.rbegin();//XXXXXXXXX modify db_reverse_iterator, use twin type
+ for (i = n - 1, crsitr = svi.rbegin(); critr != tmpvi.rend(); ++critr, ++crsitr, i--) {
+ check_expr(crsitr < crsitr + 1);
+ check_expr(critr < critr + 1);
+ check_expr(critr <= critr + 1);
+
+
+ check_expr(critr > critr - 1);
+ check_expr(critr >= critr - 1);
+ if (i > 0) {
+ ptype<int> tmpv1 = critr[1];
+ int tmpv2 = crsitr[1];
+ check_expr(tmpv1 == tmpv2);
+ }
+
+ check_expr(critr <= 2 + critr);
+ //if (i < n - 2)
+ check_expr(critr >= -2 + critr);
+ check_expr(*critr == *crsitr);
+ }
+
+ for (critr = ctmpvi.rbegin(), crsitr = svi.rbegin(), i = 0; critr != ctmpvi.rend(); critr += 3, crsitr += 3, i++) {
+ check_expr(*critr == *crsitr);
+ if (i > 0) {
+ critr -= 2;
+ crsitr -= 2;
+ }
+ check_expr(*critr == *crsitr);
+ }
+
+ for (citr2 = tmpvi.begin(), csitr2 = svi.begin(), i = 0; citr2 != tmpvi.rend(); ++citr2, ++csitr2, i++) {
+ check_expr(citr2 < citr2 + 1);
+ check_expr(citr2 <= citr2 + 1);
+ check_expr(citr2 > citr2 - 1);
+ check_expr(citr2 >= citr2 - 1);
+ check_expr(citr2 <= 2 + citr2);
+
+ if (i > 1)
+ check_expr(citr2 >= -2 + citr2);
+ check_expr(*citr2 == *csitr2);
+ if (i < n - 1)
+ check_expr(citr2[1] == csitr2[1]);
+ }
+
+ for (citr2 = ctmpvi.begin(), csitr2 = svi.begin(), i = 0; citr2 != ctmpvi.rend(); citr2 += 3, csitr2 += 3, i++) {
+ citr2.refresh(true);
+ check_expr(*citr2 == *csitr2);
+ if (i > 0) {
+ citr2 -= 2;
+ csitr2 -= 2;
+ }
+ check_expr(*citr2 == *csitr2);
+ check_expr(citr2->v == *csitr2);
+ }
+ citr2 = ctmpvi.begin() + 2;
+ csitr2 = svi.begin() + 2;
+ check_expr(*citr2 == *csitr2);
+ citr2--;
+ csitr2--;
+ check_expr(*citr2 == *csitr2);
+ --citr2;
+ --csitr2;
+ check_expr(*citr2 == *csitr2);
+
+ db_vector<ptype<int> > tmpvi2;
+ vector<int> tmpsvi2;
+ tmpvi2.insert(tmpvi2.begin(), tmpvi.begin() + 1, tmpvi.end() - 1);
+ //tmpsvi2.insert(svi.begin(), svi.begin() + 1, svi.end() - 1); c++ stl does not support this
+ for (i = 1; i < (int)tmpvi.size() - 1; i++)
+ tmpsvi2.push_back(tmpvi[i]);
+ check_expr(is_equal(tmpvi2, tmpsvi2));
+
+ tmpvi2.clear(false);
+ tmpsvi2.clear();
+
+ tmpvi2.insert(tmpvi2.end(), tmpvi.begin(), tmpvi.end());
+ tmpsvi2.insert(tmpsvi2.end(), svi.begin(), svi.end());
+ check_expr(is_equal(tmpvi2, tmpsvi2));
+
+ tmpvi2.insert(tmpvi2.end() - 3, tmpvi.begin() + 2, tmpvi.end() - 1);
+ tmpsvi2.insert(tmpsvi2.end() - 3, svi.begin() + 2, svi.end() - 1);
+ check_expr(is_equal(tmpvi2, tmpsvi2));
+
+ db_vector<char, ElementHolder<char> > charvec(n);
+ for (i = 0; i < n; i++)
+ charvec[i] = (char)i;
+ db_vector<char, ElementHolder<char> > charvec3(charvec);
+ const db_vector<char, ElementHolder<char> > &ccharvec3 = charvec3;
+ check_expr(ctmpvi == charvec);
+ charvec[n / 2] *= 2;
+ check_expr(ctmpvi != charvec);
+ charvec.push_back(127);
+ check_expr(ctmpvi != charvec);
+ charvec.resize(charvec.size());
+ charvec.assign(ccharvec3.begin(), ccharvec3.end());
+ check_expr(charvec == ccharvec3);
+ charvec.clear(false);
+ charvec.insert(charvec.begin(), ccharvec3.begin(), ccharvec3.end());
+ charvec.insert(charvec.begin(), 113);
+ db_vector<char, ElementHolder<char> > charvec2(5);
+ charvec2.assign(charvec.begin(), charvec.end(), false);
+ check_expr((charvec2 != charvec) == false);
+
+ db_vector<string> tmpvi3, tmpvi4;
+ db_vector<char *, ElementHolder<char *> > tmpvi5, tmpvi6;
+
+ std::list<string> tmpsvi3, tmpsvi4;
+ char tmpbuf[4];
+ tmpbuf[3] = '\0';
+ int exec_cnt = 0;
+doagain:
+ for (i = 0; i < 64; i++) {
+ tmpbuf[0] = 'a' + rand() % 3;
+ tmpbuf[1] = 'a' + rand() % 3;
+ tmpbuf[2] = 'a' + rand() % 3;
+ tmpvi3.push_back(string(tmpbuf));
+ tmpsvi3.push_back(string(tmpbuf));
+ tmpvi5.push_back(tmpbuf);
+ }
+
+ // sort
+ if (exec_cnt == 0) {
+ tmpvi5.sort(strlt0);
+ tmpvi3.sort(strlt);
+ tmpsvi3.sort(strlt);
+ } else {
+ tmpvi5.sort();
+ tmpvi3.sort();
+ tmpsvi3.sort();
+ }
+ check_expr(is_equal(tmpvi3, tmpsvi3));
+ check_expr(is_equal(tmpvi5, tmpsvi3));
+
+ // unique
+ if (exec_cnt == 0) {
+ tmpvi5.unique(streq0);
+ tmpvi3.unique(streq);
+ tmpsvi3.unique(streq);
+ } else {
+ tmpvi5.unique();
+ tmpvi3.unique();
+ tmpsvi3.unique();
+ }
+ check_expr(is_equal(tmpvi3,tmpsvi3));
+ check_expr(is_equal(tmpvi5, tmpsvi3));
+
+ // merge
+ for (i = 0; i < 64; i++) {
+ tmpbuf[0] = 'b' + rand() % 3;
+ tmpbuf[1] = 'b' + rand() % 3;
+ tmpbuf[2] = 'b' + rand() % 3;
+ tmpvi4.push_back(string(tmpbuf));
+ tmpsvi4.push_back(string(tmpbuf));
+ tmpvi6.push_back(tmpbuf);
+ }
+
+ if (exec_cnt == 0) {
+ tmpvi6.sort(strlt0);
+ tmpvi4.sort(strlt);
+ tmpsvi4.sort(strlt);
+ tmpvi5.merge(tmpvi6, strlt0);
+ tmpvi3.merge(tmpvi4, strlt);
+ tmpsvi3.merge(tmpsvi4, strlt);
+ } else {
+ tmpvi6.sort();
+ tmpvi4.sort();
+ tmpsvi4.sort();
+ tmpvi5.merge(tmpvi6);
+ tmpvi3.merge(tmpvi4);
+ tmpsvi3.merge(tmpsvi4);
+ }
+ check_expr(is_equal(tmpvi3, tmpsvi3));
+ check_expr(is_equal(tmpvi5, tmpsvi3));
+
+ exec_cnt++;
+ if (exec_cnt == 1) {
+ tmpvi3.clear();
+ tmpvi4.clear();
+ tmpvi5.clear();
+ tmpvi6.clear();
+ tmpsvi3.clear();
+ tmpsvi4.clear();
+ goto doagain;
+ }
+ vi.clear();
+ svi.clear();
+ }
+
+ vi.clear();
+ // tested: push_back, operator!= , db_vector::size,
+ fill(vi, svi, 0, n);
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ ptint tmp;
+
+ // tested functions:
+ // db_vector<>::begin, end; iterator::operator ++/*/=,
+ // iterator copy constructor, RandDbc<>::operator=,
+ // RandDbc<>(const RandDbc&),
+ // T(const RandDbc<T>&),
+ // RandDbc<T>::operator=(const RandDbc<T>&),
+ // and also the reverse iterator versions of these functions/classes
+ //
+ for(itr1 = vi.begin(), itr = itr1, sitr1 = svi.begin(),
+ sitr = sitr1, i = 0;
+ itr1 != vi.end() && sitr1 != svi.end(); itr1++, sitr1++, i++) {
+
+ *itr = (tmp = ptint(*itr1) * 2);
+ cout<<"\n*itr = "<<(ptint(*itr))<<"\ttmp = "<<tmp;
+ itr = itr1;
+ *sitr = (*sitr1) * 2;
+ sitr = sitr1;
+ }
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ size_t ii;
+ for(itr1 = vi.begin(), sitr1 = svi.begin(), ii = 0;
+ ii < svi.size(); ii++) {
+ itr1[ii] = 2 * itr1[ii];
+ sitr1[ii] = 2 * sitr1[ii];
+ }
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ //itr.close_cursor();
+ if ( EXPLICIT_TXN) {
+
+ dbstl::commit_txn(penv);
+ dbstl::begin_txn(0, penv);
+ }
+ for(ritr1 = vi.rbegin(), ritr = ritr1, rsitr1 = svi.rbegin(),
+ rsitr = rsitr1, i = 0;
+ ritr1 != vi.rend() && rsitr1 != svi.rend();
+ ritr1++, rsitr1++, i++) {
+
+ *ritr = (tmp = (*ritr1 * 2));
+ cout<<"\n*itr = "<<(ptint(*ritr))<<"\ttmp = "<<tmp;
+ ritr = ritr1;
+ *rsitr = *rsitr1 * 2;
+ rsitr = rsitr1;
+ }
+
+ if (EXPLICIT_TXN) {
+
+ dbstl::commit_txn(penv);
+ dbstl::begin_txn(0, penv);
+ }
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+
+ for(ritr1 = vi.rbegin(), ritr = ritr1, rsitr1 = svi.rbegin(),
+ rsitr = rsitr1, i = 0;
+ ritr1 != vi.rend() && rsitr1 != svi.rend();
+ ritr1++, rsitr1++, i++) {
+
+ *ritr = (tmp = ptint(*ritr1) * 2);
+ cout<<"\n*itr = "<<(ptint(*ritr))<<"\ttmp = "<<tmp;
+ ritr = ritr1;
+ *rsitr = (*rsitr1) * 2;
+ rsitr = rsitr1;
+ }
+
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ if (EXPLICIT_TXN){
+ dbstl::commit_txn(penv);
+ dbstl::begin_txn(0, penv);
+ }
+ for(itr1 = vi.begin(), itr = itr1, sitr1 = svi.begin(),
+ sitr = sitr1, i = 0;
+ itr1 != vi.end() && sitr1 != svi.end();
+ itr1++, sitr1++, i++) {
+
+ *itr = (tmp = ptint(*itr1) * 2);
+ cout<<"\n*itr = "<<(ptint(*itr))<<"\ttmp = "<<tmp;
+ itr = itr1;
+ *sitr = (*sitr1) * 2;
+ sitr = sitr1;
+ }
+
+ itr.close_cursor();
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ if (EXPLICIT_TXN) {
+
+ dbstl::commit_txn(penv);
+ dbstl::begin_txn(0, penv);
+ }
+
+ for (i = 0; i< n - 1; i++) {
+ vi[i] = ptint(vi[i]) * 2;
+ vi[i] = TOINT( ptint(vi[i]) - (ptint(vi[i + 1]) * 2));
+
+ svi[i] = svi[i] * 2;
+ svi[i] = TOINT(svi[i] - svi[i + 1] * 2);
+
+ }
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+ if (EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+
+ // testing pop_back and back()
+ ptint t;
+ for (i = n - 1; i >= 0; i--) {
+ check_expr(ptint(vi.back()) == svi[i]);
+ vi.pop_back();
+ }
+
+ list<int> lvi;
+ list<int>::iterator lvit;
+ for (i = 0; i < n; i++) {
+ lvi.push_front(i);
+ vi.push_front(i);
+ }
+ pprint(vi, "inserted by push_front");
+ for (i = 0; i < n; i++) {
+ pprint(vi, "pop front :");
+ check_expr(ptint(vi.front()) == lvi.front());
+ vi.pop_front();
+ lvi.pop_front();
+ }
+ fill(vi, svi, 0, n);
+ if ( !TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+ //testing front(), erase()
+ cout<<"front test\n";
+ for (i = 0, itr = vi.begin(); i < n; i++) {
+ pprint(vi);
+ check_expr(ptint(vi.front()) == svi[i]);
+ if (i % 2) // try both
+ itr = vi.erase(itr);
+ else {
+ vi.pop_front(); // here pop_front is also OK
+ itr = vi.begin();
+ }
+ }
+ itr.close_cursor();
+ fill(vi, svi, 0, n);
+
+
+ /*
+ * Currently we can only use a ref to ref the *itr and use
+ * the ref UNTIL we store changes, rahter than
+ * use *itr multiple times, because iterator::operator* will erase
+ * changed data members. this limitation won't influence std
+ * algorithms because they all manipulate the elements in their
+ * whole, never access their members.
+ */
+ for (itr1 = vi.begin(), itr = itr1,
+ sitr1 = svi.begin(), sitr = sitr1, i = 0;
+ itr1 != vi.end() && sitr1 != svi.end();i++, itr1++, sitr1++) {
+
+ if (i % 2 == 0) {
+ ptint_vector::iterator::reference itrref = (*itr);
+ t = itrref;
+ check_expr( t == *sitr);
+ itrref = (t) * 3;
+ (*sitr) = 3 * (*sitr);
+ itrref._DB_STL_StoreElement();
+ itr = itr1;
+ sitr = sitr1;
+
+ } else {
+ ptint_vector::reference itrref = vi[i];
+ t = itrref;
+ check_expr(t == svi[i]);
+ itrref = t * 3;
+ svi[i] = 3 * svi[i];
+ itrref._DB_STL_StoreElement();
+ }
+
+ }
+ pprint(vi);
+ check_expr(is_equal(vi, svi) == true);
+
+ ptint_vector vi2(db2, penv);
+ vi2.clear();
+
+ vi2.insert(vi2.end(), 1024);
+ svi2.insert(svi2.end(), 1024);
+ check_expr(is_equal(vi2, svi2) == true);
+ if ( EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ pprint(vi, "vi before swapping: ");
+ fill(vi2, svi2, 6, 9);
+ check_expr(vi != vi2);
+ pprint(vi, "vi before swapping2:");
+ pprint(vi2, "vi2 before swapping: ");
+ vi.swap(vi2);
+ check_expr(vi != vi2);
+ svi.swap(svi2);
+ pprint(vi, "vi:");
+ pprint(vi2, "vi2:");
+ check_expr(is_equal(vi, svi) == true);
+ check_expr(is_equal(vi2, svi2) == true);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ cout<<"\ntesting db container's insert method...";
+ vi.insert(vi.end(), 1024);
+ svi.insert(svi.end(), 1024);
+ vi.insert(vi.begin(), vi2.begin(), vi2.end());
+ svi.insert(svi.begin(), svi2.begin(), svi2.end());
+ vi.insert(vi.begin() + 3, 10101);
+ svi.insert(svi.begin() + 3, 10101);
+ vi.insert(vi.end(), (size_t)10, ptint (987));
+ svi.insert(svi.end(), 10, 987);
+ check_expr(is_equal(vi, svi) == true);
+ vi.insert(vi.end(), vi2.begin() + 3, vi2.end());
+ svi.insert(svi.end(), svi2.begin() + 3, svi2.end());
+ pprint(vi, "\nvi after inserting a range and 10 identical numbers");
+ check_expr(is_equal(vi, svi) == true);
+
+ vi.assign(vi2.begin(), vi2.end());
+ svi.assign(svi2.begin(), svi2.end());
+ check_expr(is_equal(vi, svi) == true);
+
+ vi.assign(vi2.begin(), vi2.end());
+ svi.assign(svi2.begin(), svi2.end());
+ check_expr(is_equal(vi, svi) == true);
+ pprint(vi, "vi before assigning");
+
+ vi.assign(vi2.begin() + 1, vi2.begin() + 3);
+ svi.assign(svi2.begin() + 1, svi2.begin() + 3);
+ check_expr(is_equal(vi, svi) == true);
+ vi.assign((size_t)10, ptint (141));
+ svi.assign(10, 141);
+ check_expr(is_equal(vi, svi) == true);
+
+ vi.insert(vi.begin(), vi2.begin(), vi2.end());
+ svi.insert(svi.begin(), svi2.begin(), svi2.end());
+
+ vi.resize(vi.size() / 2);
+ svi.resize(svi.size() / 2);
+ check_expr(is_equal(vi, svi) == true);
+ vi.resize(vi.size() * 4);
+ svi.resize(svi.size() * 4);
+ check_expr(is_equal(vi, svi) == true);
+
+ for (int ui = 0; ui < (int)svi.size(); ui++) {
+ svi[ui] = ui;
+ vi[ui] = ui;
+ }
+
+ itr = vi.begin() + 3;
+ itr1 = vi.begin() + vi.size() - 8;
+ sitr = svi.begin() + 3;
+ sitr1 = svi.begin() + svi.size() - 8;
+ pprint(vi, "vi before erasing range: ");
+ vi.erase(itr, itr1);
+ svi.erase(sitr, sitr1);
+ check_expr(is_equal(vi, svi) == true);
+
+ vi.clear();
+ svi.clear();
+ if ( EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+} // test_member_functions
+
+// Testing list specific methods.
+void TestVector::test_list_specific_member_functions()
+{
+ int i;
+ std::list<ptint> slvi;
+ std::list<ptint>::iterator slitr;
+ ptint_vector vi(db, penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ fill(vi, svi, 1,10);
+ for (i = 1; i < 11; i++)
+ slvi.push_back(i);
+ pprint(vi, "vi after fill: ");
+ vi.push_back(8);
+ vi.push_back(1);
+ vi.push_front(2);
+ vi.push_front(100);
+ vi.insert(vi.begin() + 4, 7);
+ slvi.push_back(8);
+ slvi.push_back(1);
+ slvi.push_front(2);
+ slvi.push_front(100);
+ slitr = slvi.begin();
+ std::advance(slitr, 4);
+ slvi.insert(slitr, 7);
+ pprint(vi, "vi after push_back: ");
+
+ vi.remove(8);
+ slvi.remove(8);
+ pprint(vi, "vi after remove(8): ");
+ check_expr(is_equal(vi, slvi));
+ vi.remove_if(is7);
+ slvi.remove_if(is7);
+ check_expr(is_equal(vi, slvi));
+
+ vi.reverse();
+ slvi.reverse();
+ check_expr(is_equal(vi, slvi));
+
+ vi.sort();
+ slvi.sort();
+ check_expr(is_equal(vi, slvi));
+
+ vi.push_back(100);
+ slvi.push_back(100);
+ vi.push_front(1);
+ slvi.push_front(1);
+ pprint(vi, "vi before vi.unique():");
+ vi.unique();
+ slvi.unique();
+ pprint(vi, "vi after vi.unique():");
+ check_expr(is_equal(vi, slvi));
+
+ ptint_vector vi3(db3, penv);
+ list<ptint> slvi3;
+
+ fill(vi3, svi, 4, 15);
+ for (i = 4; i < 19; i++)
+ slvi3.push_back(i);
+
+ vi.merge(vi3);
+ slvi.merge(slvi3);
+ check_expr(is_equal(vi, slvi));
+ pprint(vi3, "vi3 after merge:");
+ check_expr(is_equal(vi3, slvi3));
+
+ vi3.clear();
+ slvi3.clear();
+ svi.clear();
+ fill(vi3, svi, 4, 15);
+ for (i = 4; i < 19; i++)
+ slvi3.push_back(i);
+
+ list<ptint>::iterator slitr2;
+ slitr = slvi3.begin();
+ std::advance(slitr, 4);
+ slitr2 = slvi.begin();
+ std::advance(slitr2, 6);
+
+ pprint(vi, "vi before splice :");
+ vi.splice(vi.begin() + 6, vi3, vi3.begin() + 4);
+ slvi.splice(slitr2, slvi3, slitr);
+ pprint(vi, "vi after splice :");
+ check_expr(is_equal(vi, slvi));
+ pprint(vi3, "vi3 after splice :");
+ check_expr(is_equal(vi3, slvi3));
+
+ slitr = slvi3.begin();
+ std::advance(slitr, 5);
+ vi.splice(vi.begin(), vi3, vi3.begin() + 5, vi3.end());
+ slvi.splice(slvi.begin(), slvi3, slitr, slvi3.end());
+ pprint(vi, "vi after splice :");
+ pprint(vi3, "vi3 after splice :");
+ check_expr(is_equal(vi, slvi));
+ check_expr(is_equal(vi3, slvi3));
+
+ vi.splice(vi.end(), vi3);
+ slvi.splice(slvi.end(), slvi3);
+ pprint(vi, "vi after splice :");
+ pprint(vi3, "vi3 after splice :");
+ check_expr(is_equal(vi, slvi));
+ check_expr(is_equal(vi3, slvi3));
+
+ vi.clear();
+ vi3.clear();
+
+ check_expr(!(vi < vi3));
+ fill(vi, svi, 1, 10);
+
+ fill(vi3, svi3, 1, 10);
+ check_expr(!(vi < vi3));
+ vi.push_front(0);
+ check_expr((vi < vi3));
+ vi3.push_front(0);
+ vi.push_back(10);
+ check_expr((vi3 < vi));
+ vi.erase(vi.begin());
+ check_expr((vi3 < vi));
+
+ if ( EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+}
+
+// Use std algorithms to manipulate dbstl containers.
+void TestVector::test_std_functions()
+{
+ ptint_vector::iterator itr1, itr;
+ ptint_vector::reverse_iterator ritr1, ritr;
+ vector<int>::iterator sitr, sitr1;
+ vector<int>::reverse_iterator rsitr, rsitr1;
+ ptint_vector vi(db, penv);
+ ptint_vector vi2(db2, penv);
+ ptint_vector vi3(db3, penv);
+ // test db_vector by applying it to each and every
+ // function in std algorithm
+ //
+ // for_each
+ // here after vi is supposed to be
+ // {6, 7, 8, 9, 10, 11, 12, 13, 14}
+ //
+ if (!TEST_AUTOCOMMIT)
+ dbstl::begin_txn(0, penv);
+ vi.clear();
+ svi.clear();
+ fill(vi, svi, 6, 9);
+ if (!TEST_AUTOCOMMIT)
+ dbstl::commit_txn(penv);
+
+ if (EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ square squareobj;
+ cout<<"\nfor_each begin to end\n";
+ for_each(vi.begin(), vi.end(), squareobj);
+ cout<<endl;
+ for_each(svi.begin(), svi.end(), squareobj);
+ cout<<"\nfor_each begin +2 to begin +6\n";
+ for_each(vi.begin() + 2, vi.begin() + 6, squareobj);
+ cout<<endl;
+ for_each(svi.begin() + 2, svi.begin() + 6, squareobj);
+
+ vector<int>::difference_type ssi = svi.rend() - svi.rbegin();
+ ptint_vector::difference_type si;
+ si = vi.rend() - vi.rbegin();
+ check_expr(ssi == si);
+ vector<int>::reverse_iterator sj = svi.rbegin() + 3;
+ cout<<"si, sj ="<<si<<'\t'<<*sj;
+
+ //find
+ ptint tgt(12);
+ ptint_vector::iterator vpos =
+ find(vi.begin(), vi.end(), tgt);
+ check_expr(vpos != vi.end() && (ptint(*vpos) == tgt));
+ vpos = find(vi.begin() + 3, vi.begin() + 7, tgt);
+ check_expr(vpos != vi.end() && (ptint(*vpos) == tgt));
+ tgt = -123;
+ vpos = find(vi.begin(), vi.end(), tgt);
+ check_expr(vpos == vi.end());
+
+ // find_end
+ int subseq[] = {8, 9, 10};
+#ifdef WIN32
+ // C++ STL specification requires this equivalence relation hold for
+ // any iterators:
+ // "itr1==itr2" <===> "&*itr1 == &*itr2"
+ // this means that each iterator don't hold value for themselvs,
+ // but refer to a shared piece of memory held by its container object,
+ // which is not true for dbstl. The impl of find_end in gcc's stl lib
+ // relies on this requirement, but not for MS's stl lib. So this test
+ // only runs on WIN32.
+ pprint(vi, "vi before find_end(): ");
+ vpos = find_end(vi.begin(), vi.end(), vi.begin(), vi.begin() + 1);
+ check_expr(vpos == vi.begin());
+ vpos = find_end(vi.begin(), vi.end(), vi.begin() + 3,
+ vi.begin() + 5);
+ check_expr(vpos == vi.begin() + 3);
+ vpos = find_end(vi.begin() + 1, vi.end(), subseq, subseq + 3);
+ check_expr(vpos == vi.begin() + 2);
+#endif
+ //search
+ vpos = search(vi.begin(), vi.end(), vi.begin(), vi.begin() + 1);
+ check_expr(vpos == vi.begin());
+ vpos = search(vi.begin(), vi.end(), vi.begin() + 3, vi.begin() + 5);
+ check_expr(vpos == vi.begin() + 3);
+ vpos = search(vi.begin() + 1, vi.end(), subseq, subseq + 3);
+ check_expr(vpos == vi.begin() + 2);
+
+ // find_first_of
+ vpos = find_first_of(vi.begin(), vi.end(), vi.begin(),
+ vi.begin() + 1);
+ check_expr(vpos == vi.begin());
+ vpos = find_first_of(vi.begin() + 2, vi.begin() + 6,
+ vi.begin() + 4, vi.begin() + 5);
+ check_expr(vpos == vi.begin() + 4);
+ int subseq2[] = {9, 8, 10, 11};
+ vpos = find_first_of(vi.begin() + 1, vi.begin() + 7,
+ subseq2, subseq2 + 4);
+ check_expr(vpos == vi.begin() + 2);
+ vpos = find_first_of(vi.begin() + 6, vi.end(),
+ subseq2, subseq2 + 4);
+ check_expr(vpos == vi.end());
+
+ //find_if
+ vpos = find_if(vi.begin(), vi.end(), is2digits);
+ check_expr(ptint(*vpos) == 10);
+ vpos = find_if(vi.begin() + 5, vi.begin() + 8, is2digits);
+ check_expr(ptint(*vpos) == 11);
+ vpos = find_if(vi.begin() + 1, vi.begin() + 3, is2digits);
+ check_expr(vpos == vi.begin() + 3);
+
+ // count_if
+ ptint_vector::difference_type oddcnt =
+ count_if(vi.begin(), vi.end(), is_odd);
+ check_expr(oddcnt == 4);
+ oddcnt = count_if(vi.begin(), vi.begin() + 5, is_odd);
+ check_expr(oddcnt == 2);
+ oddcnt = count_if(vi.begin(), vi.begin(), is_odd);
+ check_expr(oddcnt == 0);
+
+ // mismatch
+ pair<intvec_t::iterator , int*> resmm = mismatch(vi.begin(),
+ vi.begin() + 3, subseq);
+ check_expr(resmm.first == vi.begin() && resmm.second == subseq);
+ resmm = mismatch(vi.begin() + 2, vi.begin() + 5, subseq);
+ check_expr(resmm.first == vi.begin() + 5 && resmm.second == subseq + 3);
+ resmm = mismatch(vi.begin() + 2, vi.begin() + 4, subseq);
+ check_expr(resmm.first == vi.begin() + 4 && resmm.second == subseq + 2);
+
+ //equal
+ check_expr (equal(vi.begin(), vi.begin() + 3, subseq) == false);
+ check_expr(equal(vi.begin() + 2, vi.begin() + 5, subseq) == true);
+ check_expr(equal(vi.begin() + 2, vi.begin() + 4, subseq) == true);
+ if ( EXPLICIT_TXN) {
+ dbstl::commit_txn(penv);
+ dbstl::begin_txn(0, penv);
+ }
+ //copy
+ pprint(vi2, "\nvi2 before copying");
+ pprint(vi, "\nvi1 before copying");
+ copy(vi.begin(), vi.begin() + 3, vi2.begin() + 1);
+ copy(svi.begin(), svi.begin() + 3, svi2.begin() + 1);
+ // vi2 should be 0, 6, 7, 8,4
+ int vi22[] = { 0, 6, 7, 8,4};
+ pprint(vi2, "\nvi2 after copying");
+ check_expr(equal(vi2.begin(), vi2.end(), vi22) == true);
+ check_expr(is_equal(vi, svi));
+
+ // copy_backward
+ copy_backward(vi.begin(), vi.begin() + 3, vi.begin() + 8);
+ copy_backward(svi.begin(), svi.begin() + 3, svi.begin() + 8);
+ pprint(vi);// should be 6,7,8,9,10,6,7,8,14
+ check_expr(is_equal(vi, svi));
+
+ copy_backward(vi.begin(), vi.begin() + 4, vi.begin() + 6);
+ copy_backward(svi.begin(), svi.begin() + 4, svi.begin() + 6);
+ pprint(vi);// should be 6,7, 6,7, 8, 9, 7, 8, 14
+ check_expr(is_equal(vi, svi));
+ copy_backward(vi.begin() + 7, vi.end(), vi.begin() + 5);
+ copy_backward(svi.begin() + 7, svi.end(), svi.begin() + 5);
+ pprint(vi);//should be 6,7,6,8,14,8,14,8,14
+ check_expr(is_equal(vi, svi)); //here the check_expr fails but I think
+ //the values in vi are right, those in svi are wrong
+
+
+ // swap_ranges
+ swap_ranges(vi.begin() + 3, vi.begin() + 7, vi.begin() + 4);
+ swap_ranges(svi.begin() + 3, svi.begin() + 7, svi.begin() + 4);
+ check_expr(is_equal(vi, svi));
+
+ /*
+ * std::swap can only swap data of same type, so following tests
+ * do not compile, we can provide our own swap(T, ElementRef<T>)
+ * func to address this
+ */
+ vector<ptint> spvi, spvi2;
+ spvi.insert(spvi.begin(), svi.begin(), svi.end());
+ spvi2.insert(spvi2.begin(), svi2.begin(), svi2.end());
+ swap_ranges(vi.begin() + 3, vi.begin() + 5, spvi.begin() + 6);
+ swap_ranges(spvi.begin() + 3, spvi.begin() + 5, vi.begin() + 6);
+ check_expr(is_equal(vi, spvi));
+
+ swap_ranges(spvi.begin() + 3, spvi.begin() + 7, vi.begin() + 5);
+ //swap back
+ swap_ranges(spvi.begin() + 3, spvi.begin() + 7, vi.begin() + 5);
+ check_expr(is_equal(vi, spvi));
+
+ transform(vi2.begin(), vi2.end(), vi.begin() + 2,
+ vi.begin() + 4, addup);
+ transform(spvi2.begin(), spvi2.end(), spvi.begin() + 2,
+ spvi.begin() + 4, addup);
+ check_expr(is_equal(vi, spvi));
+
+ replace(vi.begin(), vi.end(), 8, 88);
+ replace(spvi.begin(), spvi.end(), 8, 88);
+ check_expr(is_equal(vi, spvi));
+
+ generate(vi.begin(), vi.begin() + 2, randint);
+ generate(spvi.begin(), spvi.begin() + 2, randint);
+ pprint(vi);
+ check_expr(is_equal(vi, spvi));
+
+ remove(vi.begin(), vi.end(), -999);
+ remove(spvi.begin(), spvi.end(), -999);
+ pprint(vi, "\nafter remove");
+ check_expr(is_equal(vi, spvi));
+
+ reverse(vi.begin(), vi.end());
+ reverse(spvi.begin(), spvi.end());
+ pprint(vi, "\nafter reverse");
+ check_expr(is_equal(vi, spvi));
+
+ rotate(vi.begin() + 1, vi.begin() + 5, vi.end());
+ rotate(spvi.begin() + 1, spvi.begin() + 5, spvi.end());
+ pprint(vi, "\n after rotate");
+ check_expr(is_equal(vi, spvi));
+
+ separator<ptint> part;
+ part.mid = 11;
+ partition(vi.begin(), vi.end(), part);
+ partition(spvi.begin(), spvi.end(), part);
+ pprint(vi, "\nafter partition");
+ check_expr(is_equal(vi, spvi));
+
+ sort(vi.begin(), vi.end());
+ sort(spvi.begin(), spvi.end());
+ check_expr(is_equal(vi, spvi));
+
+ random_shuffle(vi.begin(), vi.end());
+ random_shuffle(spvi.begin(), spvi.end());
+ pprint(vi, "\nvi after random_shuffle");
+ sort(vi.begin(), vi.end());
+ sort(spvi.begin(), spvi.end());
+ pprint(vi, "\nvi after sort");
+ check_expr(is_equal(vi, spvi));
+
+ random_shuffle(vi2.begin(), vi2.end());
+ random_shuffle(spvi2.begin(), spvi2.end());
+#ifdef WIN32
+ // The implementation of __get_temporary_buffer in g++'s stl
+ // lib makes it impossible to correctly use ElementHolder or
+ // ElementRef<>, so this function dose not work with dbstl on gcc.
+ stable_sort(vi2.begin(), vi2.end());
+ stable_sort(spvi2.begin(), spvi2.end());
+#else
+ sort(vi2.begin(), vi2.end());
+ sort(spvi2.begin(), spvi2.end());
+#endif
+ check_expr(is_equal(vi2, spvi2));
+
+ random_shuffle(vi2.begin(), vi2.end());
+ random_shuffle(spvi2.begin(), spvi2.end());
+ pprint(vi2);
+ sort(vi2.begin(), vi2.end());
+ sort(spvi2.begin(), spvi2.end());
+ pprint(vi2);
+ check_expr(is_equal(vi2, spvi2));
+
+ vi3.clear();
+ vi3.insert(vi3.begin(), (size_t)100, ptint(0));
+ vector<ptint> spvi3(100);
+ merge(vi.begin(), vi.end(), vi2.begin(), vi2.end(), vi3.begin());
+ merge(spvi.begin(), spvi.end(), spvi2.begin(), spvi2.end(),
+ spvi3.begin());
+ pprint(vi3, "\n vi3 after merge vi1 with vi2:");
+ check_expr(is_equal(vi3, spvi3));
+
+ spvi3.clear();
+ vi3.clear();
+ sort(vi2.begin(), vi2.end());
+ sort(spvi2.begin(), spvi2.end());
+ pprint(vi2, "\nvi2 after sort:");
+ vi3.insert(vi3.begin(), vi2.begin(), vi2.end());
+ pprint(vi3, "\nvi3 after insert vi2 at beginning");
+ spvi3.insert(spvi3.begin(), spvi2.begin(), spvi2.end());
+ vi3.insert(vi3.begin(), vi.begin(), vi.end());
+ spvi3.insert(spvi3.begin(), spvi.begin(), spvi.end());
+ pprint(vi3, "\nvi3: v1 v2 combined in this order");
+#ifdef WIN32
+ // The implementation of __get_temporary_buffer in g++'s stl
+ // lib makes it impossible to correctly use ElementHolder or
+ // ElementRef<>, so this function dose not work with dbstl on gcc.
+ inplace_merge(vi3.begin(), vi3.begin() + (vi.end() - vi.begin()),
+ vi3.end());
+ inplace_merge(spvi3.begin(), spvi3.begin() + (spvi.end() -
+ spvi.begin()), spvi3.end());
+#endif
+ check_expr(is_equal(vi3, spvi3));
+ make_heap(vi3.begin(), vi3.end());
+ make_heap(spvi3.begin(), spvi3.end());
+ check_expr(is_equal(vi3, spvi3));
+ cout<<endl<<"pop_heap test"<<endl;
+
+ int r ;
+ int rdcnt = 0;
+ while (vi3.size() > 0) {
+ rdcnt++;
+
+ pop_heap(vi3.begin(), vi3.end());
+ vi3.pop_back();
+ pop_heap(spvi3.begin(), spvi3.end());
+ spvi3.pop_back();
+ pprint(vi3);
+
+ }
+ cout<<endl<<"push_heap test"<<endl;
+ rdcnt = 0;
+ while (vi3.size() < 10) {
+ rdcnt++;
+ r = rand();
+ vi3.push_back(ptint(r));
+ push_heap(vi3.begin(), vi3.end());
+ spvi3.push_back(ptint(r));
+ push_heap(spvi3.begin(), spvi3.end());
+ check_expr(is_equal(vi3, spvi3));
+ }
+
+ vi.clear();
+ vi2.clear();
+ vi3.clear();
+ if ( EXPLICIT_TXN)
+ dbstl::commit_txn(penv);
+
+} // void test_std_functions()
+
+void TestVector::test_primitive()
+{
+
+ int i;
+
+ if ( EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+
+
+ db_vector<int, ElementHolder<int> > ivi(db, penv);
+ vector<int> spvi4;
+ fill(ivi, spvi4);
+ check_expr(is_equal(ivi, spvi4));
+ ivi.clear(false);
+
+ db_vector<int, ElementHolder<int> > ivi2(db, 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);
+
+ db_vector<ptype<int> > ivi3(db, penv);
+ vector<int> spvi6;
+ fill(ivi3, spvi6);
+ check_expr(is_equal(ivi3, spvi6));
+ ivi3.clear(false);
+
+ typedef db_vector<double, ElementHolder<double> > dbl_vct_t;
+ dbl_vct_t dvi(db, 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<<"\ndvi after math operations: \n";
+ pprint(dvi);
+ 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);
+} // test_primitive
+
+void TestVector::test_queue_stack()
+{
+ int i;
+
+ if ( EXPLICIT_TXN)
+ dbstl::begin_txn(0, penv);
+ ptint_vector vi3(db3, penv);
+ // test whether db_vector works with std::queue,
+ // std::priority_queue and std::stack
+ cout<<"\n_testing db_vector working with std::queue\n";
+ vi3.clear();
+
+ // 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<<"\n_testing db_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<<"\n_testing db_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;
+} // test_queue_stack