コード例 #1
0
ファイル: cyrusdb_lmdb.c プロジェクト: elliefm/cyrus-imapd
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;
}
コード例 #2
0
ファイル: cyrusdb_lmdb.c プロジェクト: elliefm/cyrus-imapd
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;
}
コード例 #3
0
// 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));
}
コード例 #4
0
ファイル: cyrusdb_lmdb.c プロジェクト: elliefm/cyrus-imapd
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;
}
コード例 #5
0
void StlAdvancedFeaturesExample::arbitrary_object_storage()
{
	int i;

	if (explicit_txn)
		begin_txn(0, penv);
	// varying length objects test
	cout<<"\nArbitary object storage using Dbt..\n";
	
	rand_str_dbt smsdbt;
	DbstlDbt dbt, dbtmsg;
	string msgstr;
	SMSMsg *smsmsgs[10];

	dbtmsg.set_flags(DB_DBT_USERMEM);
	dbt.set_data(DbstlMalloc(256));
	dbt.set_flags(DB_DBT_USERMEM);
	dbt.set_ulen(256);
	db_map<int, DbstlDbt> msgmap(dbp3, penv);
	for (i = 0; i < 10; i++) {
		smsdbt(dbt, msgstr, 10, 200);
		SMSMsg *pmsg = SMSMsg::make_sms_msg(time(NULL), 
		    (char *)dbt.get_data(), i);
		smsmsgs[i] = SMSMsg::make_sms_msg(time(NULL), 
		    (char *)dbt.get_data(), i);
		dbtmsg.set_data(pmsg);
		dbtmsg.set_ulen((u_int32_t)(pmsg->mysize));
		dbtmsg.set_size((u_int32_t)(pmsg->mysize));
		dbtmsg.set_flags(DB_DBT_USERMEM);
		msgmap.insert(make_pair(i, dbtmsg));
		free(pmsg);
		memset(&dbtmsg, 0, sizeof(dbtmsg));
	}
	dbtmsg.set_data(NULL);

	SMSMsg *psmsmsg;
	for (i = 0; i < 10; i++) {
		db_map<int, DbstlDbt>::data_type_wrap msgref = msgmap[i];
		psmsmsg = (SMSMsg *)msgref.get_data();
		check_expr(memcmp(smsmsgs[i], psmsmsg, 
		    smsmsgs[i]->mysize) == 0);
	}

	i = 0;
	for (db_map<int, DbstlDbt>::iterator msgitr = 
	    msgmap.begin(ReadModifyWriteOption::
	    read_modify_write()); msgitr != msgmap.end(); ++msgitr, i++) {
		db_map<int, DbstlDbt>::reference smsmsg = *msgitr;
		(((SMSMsg*)(smsmsg.second.get_data())))->when = time(NULL);
		smsmsg.second._DB_STL_StoreElement();
		
	}

	for (i = 0; i < 10; i++) 
		free(smsmsgs[i]);
	
	msgmap.clear();


	cout<<"\nArbitary object(sparse, varying length) storage support using registered callbacks.\n";
	db_map<int, SMSMsg2> msgmap2(dbp3, penv);
	SMSMsg2 smsmsgs2[10];
	DbstlElemTraits<SMSMsg2>::instance()->set_copy_function(SMSMsgCopy);
	DbstlElemTraits<SMSMsg2>::instance()->set_size_function(SMSMsgSize);
	DbstlElemTraits<SMSMsg2>::instance()->set_restore_function(SMSMsgRestore);
	// use new technique to store varying length and inconsecutive objs
	for (i = 0; i < 10; i++) {
		smsdbt(dbt, msgstr, 10, 200);
		SMSMsg2 msg2(time(NULL), msgstr.c_str(), i);
		smsmsgs2[i] = msg2;
		
		msgmap2.insert(make_pair(i, msg2));
	 
	}
	
	// check that retrieved data is identical to stored data
	SMSMsg2 tmpmsg2;
	for (i = 0; i < 10; i++) {
		tmpmsg2 = msgmap2[i];
		check_expr(smsmsgs2[i] == tmpmsg2);
	}
	for (db_map<int, SMSMsg2>::iterator msgitr = 
	    msgmap2.begin(ReadModifyWriteOption::
	    read_modify_write()); msgitr != msgmap2.end(); msgitr++) {
		    db_map<int, SMSMsg2>::reference smsmsg = *msgitr;
		smsmsg.second.when = time(NULL);
		smsmsg.second._DB_STL_StoreElement();
		
	}
	msgmap2.clear();
	if (explicit_txn)
		commit_txn(penv);
} // arbitrary_object_storage