dbTalk Databases Forums  

transactions

comp.databases.berkeley-db comp.databases.berkeley-db


Discuss transactions in the comp.databases.berkeley-db forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
hocatka@yahoo.com
 
Posts: n/a

Default transactions - 04-04-2006 , 01:33 AM






I've been trying to implement a simple transaction implementation, very
basic and got stuck. I am following examples in the documentation, but
possibly missing something very obvious.

The code checks for the key and inserts key/value pair if the key
doesn't exist. It inserts successfully, and even if I do strings on the
database file I actually can see key/value, but when I run it again, it
can't find the key, and get ALWAYS returns DB_NOTFOUND.

---------------------

#include <stdio.h>
#include <stdlib.h>

#include "db.h"

int
main(void)
{
int ret, ret_c;
u_int32_t db_flags, env_flags;
DB *dbp;
DB_ENV *envp;
DBT key, data;
DB_TXN *txn;
const char *db_home_dir = "/tmp";
const char *file_name = "mydb.db";
const char keystr[] ="thekey";
const char datastr[] = "thedata";

dbp = NULL;
envp = NULL;

/* Open the environment */
ret = db_env_create(&envp, 0);
if (ret != 0) {
fprintf(stderr, "Error creating environment handle: %s\n",
db_strerror(ret));
return (EXIT_FAILURE);
}

env_flags = DB_CREATE | /* Create the environment if it does
* not already exist. */
DB_INIT_TXN | /* Initialize transactions */
DB_INIT_LOCK | /* Initialize locking. */
DB_INIT_LOG | /* Initialize logging */
DB_INIT_MPOOL; /* Initialize the in-memory cache. */

ret = envp->open(envp, db_home_dir, env_flags, 0);
if (ret != 0) {
fprintf(stderr, "Error opening environment: %s\n",
db_strerror(ret));
goto err;
}

/* Initialize the DB handle */
ret = db_create(&dbp, envp, 0);
if (ret != 0) {
envp->err(envp, ret, "Database creation failed");
goto err;
}

db_flags = DB_CREATE | DB_AUTO_COMMIT;
/*
* Open the database. Note that we are using auto commit for the
open,
* so the database is able to support transactions.
*/
ret = dbp->open(dbp, /* Pointer to the database */
NULL, /* Txn pointer */
file_name, /* File name */
NULL, /* Logical db name */
DB_BTREE, /* Database type (using btree) */
db_flags, /* Open flags */
0); /* File mode. Using defaults */
if (ret != 0) {
envp->err(envp, ret, "Database '%s' open failed",
file_name);
goto err;
}

/* Prepare the DBTs */
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));

key.data = &keystr;
key.size = strlen(keystr)+1;
key.ulen = strlen(keystr)+1;
key.flags = DB_DBT_USERMEM;

/* Get the txn handle */
txn = NULL;
ret = envp->txn_begin(envp, NULL, &txn, 0);
if (ret != 0) {
envp->err(envp, ret, "Transaction begin failed.");
goto err;
}


ret = dbp->get(dbp, NULL, &key, &data, 0);
if (ret != 0) {
envp->err(envp, ret, "Database get failed.");
if(ret != DB_NOTFOUND) goto err;
}

key.data = &keystr;
key.size = strlen(keystr)+1;

data.data = &datastr;
data.size = strlen(datastr)+1;

/*
* Perform the database write. If this fails, abort the
transaction.
*/
ret = dbp->put(dbp, txn, &key, &data, 0);
if (ret != 0) {
envp->err(envp, ret, "Database put failed.");
txn->abort(txn);
goto err;
}

/*
* Commit the transaction. Note that the transaction handle
* can no longer be used.
*/
ret = txn->commit(txn, 0);
if (ret != 0) {
envp->err(envp, ret, "Transaction commit failed.");
goto err;
}

err:
/* Close the database */
if (dbp != NULL) {
ret_c = dbp->close(dbp, 0);
if (ret_c != 0) {
envp->err(envp, ret_c, "Database close failed.");
ret = ret_c;
}
}


/* Close the environment */
if (envp != NULL) {
ret_c = envp->close(envp, 0);
if (ret_c != 0) {
fprintf(stderr, "environment close failed: %s\n",
db_strerror(ret_c));
ret = ret_c;
}
}

return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}


Reply With Quote
  #2  
Old   
Alex
 
Posts: n/a

Default Re: transactions - 04-04-2006 , 06:32 PM






The core issue is with the first call to get. It will fail (as
expected), and return DB_NOTFOUND.
You are testing for a result of 0, if not zero jumping to err, thus
skipping the put call.
The record is never actually being put into the DB.


Reply With Quote
  #3  
Old   
hocatka@yahoo.com
 
Posts: n/a

Default Re: transactions - 04-04-2006 , 08:25 PM



here is the first call to get:

ret = dbp->get(dbp, NULL, &key, &data, 0);
if (ret != 0) {
envp->err(envp, ret, "Database get failed.");
if(ret != DB_NOTFOUND) goto err;
}

it will jump only if it's not zero and not DB_NOTFOUND.
If it is DB_NOTFOUND it doesn't jump and I actually see record created
if I do 'strings /tmp/mydb.db'

dev# strings /tmp/mydb.db
thedata
thekey
dev#


Reply With Quote
  #4  
Old   
Alex
 
Posts: n/a

Default Re: transactions - 04-05-2006 , 01:42 AM



You are right. Sorry.

I have actually run the sample now. When stepping through in a debugger
it seems to do as expected.

The first time through get returns non-zero, and the entry is added.
The second time through get returned zero (success), and the entry is
added again.

What behaviour are you expecting to see? What behaviour are you seeing?


Reply With Quote
  #5  
Old   
hocatka@yahoo.com
 
Posts: n/a

Default Re: transactions - 04-05-2006 , 10:06 AM



In my case 'get' returns DB_NOTFOUND no matter how many times do I run
it.
I am expecting 'get' to return 0 the second time I run it. Version of
BDB is 4.4.20 if it matters. OS is Debian Sarge, 2.4.29
if it matters. I've tried different gcc versions, and upgraded
everything to the latest, but result is the same.


Reply With Quote
  #6  
Old   
Joseph Bruni
 
Posts: n/a

Default Re: transactions - 04-05-2006 , 11:02 PM




instead of using "strings" why not use the included "db_dump" utility?


"hocatka (AT) yahoo (DOT) com" <hocatka (AT) yahoo (DOT) com> wrote:
Quote:

here is the first call to get:

ret = dbp->get(dbp, NULL, &key, &data, 0);
if (ret != 0) {
envp->err(envp, ret, "Database get failed.");
if(ret != DB_NOTFOUND) goto err;
}

it will jump only if it's not zero and not DB_NOTFOUND.
If it is DB_NOTFOUND it doesn't jump and I actually see record created
if I do 'strings /tmp/mydb.db'

dev# strings /tmp/mydb.db
thedata
thekey
dev#



--




Reply With Quote
  #7  
Old   
hocatka@yahoo.com
 
Posts: n/a

Default Re: transactions - 04-06-2006 , 02:07 AM



I am new to BDB, thank you for the hint, thats what I get with db_dump:

dev# /usr/local/BerkeleyDB.4.4/bin/db_dump -p /tmp/mydb.db
VERSION=3
format=print
type=btree
db_pagesize=4096
HEADER=END
DATA=END

so, it doesn't find the record, but if I specify -R (Aggressively
salvage data from a possibly corrupt file) it does find it

dev# /usr/local/BerkeleyDB.4.4/bin/db_dump -Rp /tmp/mydb.db
VERSION=3
format=print
type=btree
HEADER=END
thekey\00
thedata\00
DATA=END

Not sure why does it happen :-\


Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.