Michael Cahill *nix forums Guru Wannabe
Joined: 26 May 2005
Posts: 219
|
Posted: Thu Apr 07, 2005 10:38 pm Post subject:
Re: Database update done by writer not visible to the reader
|
|
|
Hi,
| Quote: | db_create( &dbp, NULL, 0 );
|
You aren't creating the database in the environment. That second
parameter should be dbenv, not NULL.
Regards,
Michael. |
|
oleksandr kalinin *nix forums beginner
Joined: 07 Apr 2005
Posts: 2
|
Posted: Thu Apr 07, 2005 5:28 pm Post subject:
Database update done by writer not visible to the reader
|
|
|
Hi All,
I am wondering on how can I make sure that within the multiple-writer /
multiple-reader environment database update done by the writer will become
actual to the reader. The problem I have is that whenever the writer has
updated (or added) the record with given key, another reader process looks
up the database by that key and data appears to be old as if the writer has
not updated/added it.
The sequence of events is the following:
- Process A - creates an environment handle and open an environment with
DB_INIT_MPOOL | DB_INIT_LOCK | DB_CREATE | DB_THREAD flags set.
- Process A - creates a database file with DB_CREATE flag.
- Process B - creates an environment handle and open an environment with
DB_INIT_MPOOL | DB_INIT_LOCK | DB_THREAD flags set, using the same db_home
as Process A.
- Process B - opens a database previously created by Process A, no flags
set.
- Process A - modifies a record with some key (data used to be X, now
Y )
- Process B - retrieves a record by the same key, data is still X.
Is there anything wrong with such sequence? Am I missing any flags?
Here is an example of code, just in case:
Process A code:
#include <unistd.h>
#include <stdio.h>
#include <db.h>
#include <assert.h>
struct rec {
int x; /* key field */
int y; /* data field */
};
int main(int argc, char *argv[])
{
DB_ENV* dbenv;
DB* dbp;
DBT key, data;
struct rec r;
struct rec *pr;
int ret;
db_env_create( &dbenv, NULL );
assert( 0 == dbenv->open( dbenv, ".", DB_INIT_LOCK | DB_INIT_MPOOL |
DB_CREATE | DB_THREAD, 0) );
db_create( &dbp, NULL, 0 );
assert( 0 == dbp->open( dbp, NULL, "test.db", NULL, DB_BTREE, DB_CREATE,
0 ) );
/* First command line parameter is key, second parameter is data */
r.x = atoi( argv[1] );
r.y = atoi( argv[2] );
memset( &key, 0, sizeof(key) );
memset( &data, 0, sizeof(data) );
key.data = (void *) &r.x;
key.size = sizeof( r.x );
data.data = &r;
data.size = sizeof( r );
/* Add a record */
ret = dbp->put( dbp, NULL, &key, &data, 0 );
/* Adding dbp->sync(dbp, 0); here does not help */
/* Now retrieve a record and display data, repeat every 2 seconds */
for (;
{
memset( &key, 0, sizeof(key) );
memset( &data, 0, sizeof(data) );
key.data = (void *) &r.x;
key.size = sizeof( r.x );
dbp->get( dbp, NULL, &key, &data, 0 );
pr = (struct rec*) data.data;
if (pr != NULL)
printf( "DATA=%i\n", pr->y );
sleep(2);
}
}
Process B code is exactly the same, but without DB_CREATE flag in open
calls.
Start first process and add a record {3, 4}:
$ ./mytest 3 4
DATA=4
DATA=4
....
Start second process, while first process is running and modify a record to
become {3, 8}:
$ ./mytest 3 8
DATA=8
DATA=8
....
Second process has updated the database, but the output from first process
remains the same, as if it is sitting in some cache:
DATA=4
The change becomes actual to the reader only after re-opening the database.
I've been reading documentation for some time now, looking at other people's
code and still can't get what is wrong in the example above. Many thanks in
advance for your reply!
Best wishes,
Oleksandr |
|