static int fetch(struct dbengine *db, const char *key, size_t keylen, const char **data, size_t *datalen, struct txn **tidptr) { MDB_val mkey, mval; struct txn *tid; int r, r2 = 0, mr; PDEBUG("cyrusdb_lmdb(%s)[fetch] tidptr=%p *tidptr=%p key='%.*s'", db->fname, tidptr, tidptr ? *tidptr : NULL, (int) keylen, key); assert(db && key); mkey.mv_data = (void*) key; mkey.mv_size = keylen; /* Open or reuse transaction */ r = getorset_txn(db, tidptr, &tid, !tidptr /*readonly*/); if (r) goto fail; mr = mdb_get(tid->mtxn, tid->dbi, &mkey, &mval); if (mr == MDB_NOTFOUND) { /* That's not an error */ r = CYRUSDB_NOTFOUND; if (datalen) *datalen = 0; if (data) *data = NULL; } else if (mr) { /* That's an error */ syslog(LOG_ERR, "cryusdb_lmdb(%s): %s", db->fname, mdb_strerror(mr)); r = CYRUSDB_INTERNAL; goto fail; } else if (data && datalen) { /* Cache the fetched data from LMDB memory in own buffer */ r = bufferval(db, mval, data, datalen); if (r) goto fail; } /* Commit or export the transaction */ if (!tidptr) { r2 = commit_txn(db, tid); if (r2) goto fail; } else { *tidptr = tid; r2 = CYRUSDB_OK; } return r ? r : r2; fail: if (tid && (!tidptr || !*tidptr)) abort_txn(db, tid); return r ? r : r2; }
static int put(struct dbengine *db, const char *key, size_t keylen, const char *data, size_t datalen, struct txn **tidptr, int mflags) { MDB_val mkey, mval; struct txn *tid; int r, mr; mkey.mv_data = (void*) key; mkey.mv_size = keylen; mval.mv_data = (void*) data; mval.mv_size = datalen; /* Invalidate cursor */ if (db->mcur) { mdb_cursor_close(db->mcur); db->mcur = NULL; } /* Open or reuse transaction */ r = getorset_txn(db, tidptr, &tid, 0); if (r) goto fail; mr = mdb_put(tid->mtxn, tid->dbi, &mkey, &mval, mflags); if (mr) { /* Return the appropriate error code for existing key overwrites */ syslog(LOG_ERR, "cryusdb_lmdb(%s): %s", db->fname, mdb_strerror(mr)); r = (mr == MDB_KEYEXIST && (mflags & MDB_NOOVERWRITE)) ? \ CYRUSDB_EXISTS : CYRUSDB_INTERNAL; goto fail; } /* Commit or export the transaction */ if (!tidptr) { r = commit_txn(db, tid); if (r) goto fail; } else { *tidptr = tid; } return CYRUSDB_OK; fail: if (tid && (!tidptr || !*tidptr)) abort_txn(db, tid); return r; }
// std::string persistent test. void StlAdvancedFeaturesExample::storing_std_strings() { string kstring = "hello world", *sstring = new string("hi there"); if (explicit_txn) begin_txn(0, penv); db_map<string, string> pmap(dmstringdb, NULL); pmap[kstring] = *sstring + "!"; *sstring = pmap[kstring]; map<string, string> spmap; spmap.insert(make_pair(kstring, *sstring)); cout<<"sstring append ! is : "<<pmap[kstring] <<" ; *sstring is : "<<*sstring; delete sstring; for (db_map<string, string>::iterator ii = pmap.begin(); ii != pmap.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; } close_db(dmstringdb); dmstringdb = dbstl::open_db(penv, "db_map_stringdb.db", dbtype, DB_CREATE | dboflags, 0); db_map<string, string> pmap2(dmstringdb, NULL); for (db_map<string, string>::iterator ii = pmap2.begin(); ii != pmap2.end(); ++ii) { cout << (*ii).first << ": " << (*ii).second << endl; // assert key/data pair set equal check_expr((spmap.count(ii->first) == 1) && (spmap[ii->first] == ii->second)); } if (explicit_txn) commit_txn(penv); db_vector<string> strvctor(10); vector<string> sstrvctor(10); for (int i = 0; i < 10; i++) { strvctor[i] = "abc"; sstrvctor[i] = strvctor[i]; } check_expr(is_equal(strvctor, sstrvctor)); }
static int foreach(struct dbengine *db, const char *prefix, size_t prefixlen, foreach_p *p, foreach_cb *cb, void *rock, struct txn **tidptr) { int r, r2, mr = 0; struct txn *tid = NULL; MDB_val mkey, mval; enum MDB_cursor_op op; struct buf cur = BUF_INITIALIZER; PDEBUG("cyrusdb_lmdb(%s)[foreach] tidptr=%p *tidptr=%p prefix='%.*s'", db->fname, tidptr, tidptr ? *tidptr : NULL, (int) prefixlen, prefix); assert(db); /* Open or reuse transaction */ r = getorset_txn(db, tidptr, &tid, 0); if (r) goto fail; mr = mdb_cursor_open(tid->mtxn, tid->dbi, &db->mcur); if (mr) goto fail; /* Normalize and set prefix for search */ if (prefix && !prefixlen) { prefix = NULL; } /* Initialize cursor */ mkey.mv_data = (void*) prefix; mkey.mv_size = prefix ? prefixlen : 0; op = prefix ? MDB_SET_RANGE : MDB_FIRST; mr = mdb_cursor_get(db->mcur, &mkey, &mval, op); /* Iterate cursor until no records or out of range */ while (!mr) { if (prefixlen && (mkey.mv_size < prefixlen)) break; if (prefix && memcmp(mkey.mv_data, prefix, prefixlen)) break; if (!p || p(rock, mkey.mv_data, mkey.mv_size, mval.mv_data, mval.mv_size)) { /* Cache the current position in local memory */ buf_setmap(&cur, mkey.mv_data, mkey.mv_size); r = cb(rock, cur.s, cur.len, mval.mv_data, mval.mv_size); if (r) break; if (db->mcur == NULL) { /* An update has invalidated the cursor. Reseek cursor. */ mr = mdb_cursor_open(tid->mtxn, tid->dbi, &db->mcur); if (mr) break; mkey.mv_data = cur.s; mkey.mv_size = cur.len; mr = mdb_cursor_get(db->mcur, &mkey, &mval, MDB_SET_RANGE); if (mr) break; if (mkey.mv_size != cur.len || memcmp(mkey.mv_data, cur.s, cur.len)) { /* The current position has been deleted. */ continue; } } } /* Advance cursor */ mr = mdb_cursor_get(db->mcur, &mkey, &mval, MDB_NEXT); } if (mr && mr != MDB_NOTFOUND) goto fail; if (db->mcur) { mdb_cursor_close(db->mcur); db->mcur = NULL; } buf_free(&cur); /* Export or commit transaction */ r2 = tidptr ? CYRUSDB_OK : commit_txn(db, tid); return r ? r : r2; fail: if (db->mcur) { mdb_cursor_close(db->mcur); db->mcur = NULL; } buf_free(&cur); if (tid && (!tidptr || !*tidptr)) abort_txn(db, tid); if (mr) { syslog(LOG_ERR, "cryusdb_lmdb(%s): %s", db->fname, mdb_strerror(mr)); r = my_mdberror(mr); } return r; }
void StlAdvancedFeaturesExample::arbitrary_object_storage() { int i; if (explicit_txn) begin_txn(0, penv); // varying length objects test cout<<"\nArbitary object storage using Dbt..\n"; rand_str_dbt smsdbt; DbstlDbt dbt, dbtmsg; string msgstr; SMSMsg *smsmsgs[10]; dbtmsg.set_flags(DB_DBT_USERMEM); dbt.set_data(DbstlMalloc(256)); dbt.set_flags(DB_DBT_USERMEM); dbt.set_ulen(256); db_map<int, DbstlDbt> msgmap(dbp3, penv); for (i = 0; i < 10; i++) { smsdbt(dbt, msgstr, 10, 200); SMSMsg *pmsg = SMSMsg::make_sms_msg(time(NULL), (char *)dbt.get_data(), i); smsmsgs[i] = SMSMsg::make_sms_msg(time(NULL), (char *)dbt.get_data(), i); dbtmsg.set_data(pmsg); dbtmsg.set_ulen((u_int32_t)(pmsg->mysize)); dbtmsg.set_size((u_int32_t)(pmsg->mysize)); dbtmsg.set_flags(DB_DBT_USERMEM); msgmap.insert(make_pair(i, dbtmsg)); free(pmsg); memset(&dbtmsg, 0, sizeof(dbtmsg)); } dbtmsg.set_data(NULL); SMSMsg *psmsmsg; for (i = 0; i < 10; i++) { db_map<int, DbstlDbt>::data_type_wrap msgref = msgmap[i]; psmsmsg = (SMSMsg *)msgref.get_data(); check_expr(memcmp(smsmsgs[i], psmsmsg, smsmsgs[i]->mysize) == 0); } i = 0; for (db_map<int, DbstlDbt>::iterator msgitr = msgmap.begin(ReadModifyWriteOption:: read_modify_write()); msgitr != msgmap.end(); ++msgitr, i++) { db_map<int, DbstlDbt>::reference smsmsg = *msgitr; (((SMSMsg*)(smsmsg.second.get_data())))->when = time(NULL); smsmsg.second._DB_STL_StoreElement(); } for (i = 0; i < 10; i++) free(smsmsgs[i]); msgmap.clear(); cout<<"\nArbitary object(sparse, varying length) storage support using registered callbacks.\n"; db_map<int, SMSMsg2> msgmap2(dbp3, penv); SMSMsg2 smsmsgs2[10]; DbstlElemTraits<SMSMsg2>::instance()->set_copy_function(SMSMsgCopy); DbstlElemTraits<SMSMsg2>::instance()->set_size_function(SMSMsgSize); DbstlElemTraits<SMSMsg2>::instance()->set_restore_function(SMSMsgRestore); // use new technique to store varying length and inconsecutive objs for (i = 0; i < 10; i++) { smsdbt(dbt, msgstr, 10, 200); SMSMsg2 msg2(time(NULL), msgstr.c_str(), i); smsmsgs2[i] = msg2; msgmap2.insert(make_pair(i, msg2)); } // check that retrieved data is identical to stored data SMSMsg2 tmpmsg2; for (i = 0; i < 10; i++) { tmpmsg2 = msgmap2[i]; check_expr(smsmsgs2[i] == tmpmsg2); } for (db_map<int, SMSMsg2>::iterator msgitr = msgmap2.begin(ReadModifyWriteOption:: read_modify_write()); msgitr != msgmap2.end(); msgitr++) { db_map<int, SMSMsg2>::reference smsmsg = *msgitr; smsmsg.second.when = time(NULL); smsmsg.second._DB_STL_StoreElement(); } msgmap2.clear(); if (explicit_txn) commit_txn(penv); } // arbitrary_object_storage