Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
HAMANO Tsukasa
OpenLDAP
Commits
bc0ca49d
Commit
bc0ca49d
authored
Jul 02, 2011
by
Howard Chu
Browse files
Use an environment directory
Go back to using an mmap'd lock file
parent
5a72c6a2
Changes
2
Hide whitespace changes
Inline
Side-by-side
libraries/libmdb/Makefile
View file @
bc0ca49d
...
...
@@ -7,9 +7,10 @@ LDLIBS =
all
:
mtest mdb_stat
clean
:
rm
-f
mtest mdb_stat
*
.[ao]
*
~ testdb
rm
-
r
f
mtest mdb_stat
*
.[ao]
*
~ testdb
test
:
all
mkdir
testdb
./mtest
&&
./mdb_stat testdb
mdb_stat
:
mdb_stat.o mdb.o idl.o
...
...
libraries/libmdb/mdb.c
View file @
bc0ca49d
...
...
@@ -7,8 +7,7 @@
#ifdef HAVE_SYS_FILE_H
#include
<sys/file.h>
#endif
#include
<sys/ipc.h>
#include
<sys/shm.h>
#include
<fcntl.h>
#include
<assert.h>
#include
<err.h>
...
...
@@ -218,6 +217,7 @@ struct MDB_txn {
}
mt_u
;
#define MDB_TXN_RDONLY 0x01
/* read-only transaction */
#define MDB_TXN_ERROR 0x02
/* an error has occurred */
#define MDB_TXN_METOGGLE 0x04
/* used meta page 1 */
unsigned
int
mt_flags
;
};
...
...
@@ -233,10 +233,9 @@ struct MDB_db {
struct
MDB_env
{
int
me_fd
;
key_t
me_shmkey
;
int
me_lfd
;
uint32_t
me_flags
;
int
me_maxreaders
;
int
me_metatoggle
;
unsigned
int
me_maxreaders
;
char
*
me_path
;
char
*
me_map
;
MDB_txninfo
*
me_txns
;
...
...
@@ -274,7 +273,7 @@ static int mdb_search_page(MDB_db *db,
static
int
mdbenv_read_header
(
MDB_env
*
env
);
static
int
mdb_check_meta_page
(
MDB_page
*
p
);
static
int
mdbenv_read_meta
(
MDB_env
*
env
);
static
int
mdbenv_read_meta
(
MDB_env
*
env
,
int
*
which
);
static
int
mdbenv_write_meta
(
MDB_txn
*
txn
);
static
MDB_page
*
mdbenv_get_page
(
MDB_env
*
env
,
pgno_t
pgno
);
...
...
@@ -473,7 +472,7 @@ int
mdb_txn_begin
(
MDB_env
*
env
,
int
rdonly
,
MDB_txn
**
ret
)
{
MDB_txn
*
txn
;
int
rc
;
int
rc
,
toggle
;
if
((
txn
=
calloc
(
1
,
sizeof
(
*
txn
)))
==
NULL
)
{
DPRINTF
(
"calloc: %s"
,
strerror
(
errno
));
...
...
@@ -504,7 +503,7 @@ mdb_txn_begin(MDB_env *env, int rdonly, MDB_txn **ret)
if
(
rdonly
)
{
MDB_reader
*
r
=
pthread_getspecific
(
env
->
me_txkey
);
if
(
!
r
)
{
int
i
;
unsigned
int
i
;
pthread_mutex_lock
(
&
env
->
me_txns
->
mt_mutex
);
for
(
i
=
0
;
i
<
env
->
me_maxreaders
;
i
++
)
{
if
(
env
->
me_txns
->
mt_readers
[
i
].
mr_pid
==
0
)
{
...
...
@@ -529,11 +528,14 @@ mdb_txn_begin(MDB_env *env, int rdonly, MDB_txn **ret)
txn
->
mt_env
=
env
;
if
((
rc
=
mdbenv_read_meta
(
env
))
!=
MDB_SUCCESS
)
{
if
((
rc
=
mdbenv_read_meta
(
env
,
&
toggle
))
!=
MDB_SUCCESS
)
{
mdb_txn_abort
(
txn
);
return
rc
;
}
if
(
toggle
)
txn
->
mt_flags
|=
MDB_TXN_METOGGLE
;
txn
->
mt_next_pgno
=
env
->
me_meta
.
mm_last_pg
+
1
;
txn
->
mt_root
=
env
->
me_meta
.
mm_root
;
DPRINTF
(
"begin transaction %lu on mdbenv %p, root page %lu"
,
...
...
@@ -839,7 +841,7 @@ mdbenv_write_meta(MDB_txn *txn)
meta
.
mm_txnid
=
txn
->
mt_txnid
;
off
=
0
;
if
(
!
env
->
me_metatoggle
)
if
(
!
F_ISSET
(
txn
->
mt_flags
,
MDB_TXN_METOGGLE
)
)
off
=
env
->
me_meta
.
mm_stat
.
ms_psize
;
off
+=
PAGEHDRSZ
;
...
...
@@ -867,7 +869,7 @@ mdb_check_meta_page(MDB_page *p)
}
static
int
mdbenv_read_meta
(
MDB_env
*
env
)
mdbenv_read_meta
(
MDB_env
*
env
,
int
*
which
)
{
MDB_page
*
mp0
,
*
mp1
;
MDB_meta
*
meta
[
2
];
...
...
@@ -893,7 +895,8 @@ mdbenv_read_meta(MDB_env *env)
if
(
meta
[
toggle
]
->
mm_txnid
>
env
->
me_meta
.
mm_txnid
)
{
bcopy
(
meta
[
toggle
],
&
env
->
me_meta
,
sizeof
(
env
->
me_meta
));
env
->
me_metatoggle
=
toggle
;
if
(
which
)
*
which
=
toggle
;
}
DPRINTF
(
"Using meta page %d"
,
toggle
);
...
...
@@ -912,6 +915,8 @@ mdbenv_create(MDB_env **env)
e
->
me_meta
.
mm_mapsize
=
DEFAULT_MAPSIZE
;
e
->
me_maxreaders
=
DEFAULT_READERS
;
e
->
me_db
.
md_env
=
e
;
e
->
me_fd
=
-
1
;
e
->
me_lfd
=
-
1
;
*
env
=
e
;
return
MDB_SUCCESS
;
}
...
...
@@ -977,7 +982,7 @@ mdbenv_open2(MDB_env *env, unsigned int flags)
}
}
if
((
i
=
mdbenv_read_meta
(
env
))
!=
0
)
if
((
i
=
mdbenv_read_meta
(
env
,
NULL
))
!=
0
)
return
i
;
DPRINTF
(
"opened database version %u, pagesize %u"
,
...
...
@@ -1002,51 +1007,131 @@ mdbenv_reader_dest(void *ptr)
reader
->
mr_tid
=
0
;
}
int
mdbenv_
open
(
MDB_env
*
env
,
const
char
*
path
,
unsigned
int
flags
,
mode_t
mode
)
static
void
mdbenv_
share_locks
(
MDB_env
*
env
)
{
int
oflags
,
rc
,
shmid
;
off_t
size
;
struct
flock
lock_info
;
env
->
me_txns
->
mt_txnid
=
env
->
me_meta
.
mm_txnid
;
if
(
F_ISSET
(
flags
,
MDB_RDONLY
))
oflags
=
O_RDONLY
;
else
oflags
=
O_RDWR
|
O_CREAT
;
memset
((
void
*
)
&
lock_info
,
0
,
sizeof
(
lock_info
));
lock_info
.
l_type
=
F_RDLCK
;
lock_info
.
l_whence
=
SEEK_SET
;
lock_info
.
l_start
=
0
;
lock_info
.
l_len
=
1
;
fcntl
(
env
->
me_lfd
,
F_SETLK
,
&
lock_info
);
}
if
((
env
->
me_fd
=
open
(
path
,
oflags
,
mode
))
==
-
1
)
return
errno
;
static
int
mdbenv_setup_locks
(
MDB_env
*
env
,
char
*
lpath
,
int
mode
,
int
*
excl
)
{
int
rc
;
off_t
size
,
rsize
;
struct
flock
lock_info
;
env
->
me_shmkey
=
ftok
(
path
,
'm'
);
size
=
(
env
->
me_maxreaders
-
1
)
*
sizeof
(
MDB_reader
)
+
sizeof
(
MDB_txninfo
);
shmid
=
shmget
(
env
->
me_shmkey
,
size
,
IPC_CREAT
|
IPC_EXCL
|
mode
);
if
(
shmid
==
-
1
)
{
if
(
errno
==
EEXIST
)
{
shmid
=
shmget
(
env
->
me_shmkey
,
size
,
IPC_CREAT
|
mode
);
if
(
shmid
==
-
1
)
return
errno
;
env
->
me_txns
=
shmat
(
shmid
,
NULL
,
0
);
if
(
env
->
me_txns
->
mt_magic
!=
MDB_MAGIC
||
env
->
me_txns
->
mt_version
!=
MDB_VERSION
)
{
DPRINTF
(
"invalid lock region %d"
,
shmid
);
shmdt
(
env
->
me_txns
);
env
->
me_txns
=
NULL
;
return
EIO
;
}
}
else
{
return
errno
;
*
excl
=
0
;
if
((
env
->
me_lfd
=
open
(
lpath
,
O_RDWR
|
O_CREAT
,
mode
))
==
-
1
)
{
rc
=
errno
;
return
rc
;
}
/* Try to get exclusive lock. If we succeed, then
* nobody is using the lock region and we should initialize it.
*/
memset
((
void
*
)
&
lock_info
,
0
,
sizeof
(
lock_info
));
lock_info
.
l_type
=
F_WRLCK
;
lock_info
.
l_whence
=
SEEK_SET
;
lock_info
.
l_start
=
0
;
lock_info
.
l_len
=
1
;
rc
=
fcntl
(
env
->
me_lfd
,
F_SETLK
,
&
lock_info
);
if
(
rc
==
0
)
{
*
excl
=
1
;
}
else
{
lock_info
.
l_type
=
F_RDLCK
;
rc
=
fcntl
(
env
->
me_lfd
,
F_SETLK
,
&
lock_info
);
if
(
rc
)
{
rc
=
errno
;
goto
fail
;
}
}
size
=
lseek
(
env
->
me_lfd
,
0
,
SEEK_END
);
rsize
=
(
env
->
me_maxreaders
-
1
)
*
sizeof
(
MDB_reader
)
+
sizeof
(
MDB_txninfo
);
if
(
size
<
rsize
&&
*
excl
)
{
if
(
ftruncate
(
env
->
me_lfd
,
rsize
)
!=
0
)
{
rc
=
errno
;
goto
fail
;
}
}
else
{
rsize
=
size
;
size
=
rsize
-
sizeof
(
MDB_txninfo
);
env
->
me_maxreaders
=
size
/
sizeof
(
MDB_reader
)
+
1
;
}
env
->
me_txns
=
mmap
(
0
,
rsize
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
env
->
me_lfd
,
0
);
if
(
env
->
me_txns
==
MAP_FAILED
)
{
rc
=
errno
;
goto
fail
;
}
if
(
*
excl
)
{
pthread_mutexattr_t
mattr
;
env
->
me_txns
=
shmat
(
shmid
,
NULL
,
0
);
pthread_mutexattr_init
(
&
mattr
);
pthread_mutexattr_setpshared
(
&
mattr
,
PTHREAD_PROCESS_SHARED
);
pthread_mutex_init
(
&
env
->
me_txns
->
mt_mutex
,
&
mattr
);
pthread_mutex_init
(
&
env
->
me_txns
->
mt_wmutex
,
&
mattr
);
env
->
me_txns
->
mt_version
=
MDB_VERSION
;
env
->
me_txns
->
mt_magic
=
MDB_MAGIC
;
env
->
me_txns
->
mt_txnid
=
0
;
env
->
me_txns
->
mt_numreaders
=
0
;
}
else
{
if
(
env
->
me_txns
->
mt_magic
!=
MDB_MAGIC
)
{
DPRINTF
(
"lock region has invalid magic"
);
errno
=
EINVAL
;
}
if
(
env
->
me_txns
->
mt_version
!=
MDB_VERSION
)
{
DPRINTF
(
"lock region is version %u, expected version %u"
,
env
->
me_txns
->
mt_version
,
MDB_VERSION
);
errno
=
EINVAL
;
}
if
(
errno
!=
EACCES
&&
errno
!=
EAGAIN
)
{
rc
=
errno
;
goto
fail
;
}
}
return
MDB_SUCCESS
;
fail:
close
(
env
->
me_lfd
);
return
rc
;
}
int
mdbenv_open
(
MDB_env
*
env
,
const
char
*
path
,
unsigned
int
flags
,
mode_t
mode
)
{
int
oflags
,
rc
,
len
,
excl
;
char
*
lpath
,
*
dpath
;
len
=
strlen
(
path
);
lpath
=
malloc
(
len
+
sizeof
(
"/lock.mdb"
)
+
len
+
sizeof
(
"/data.db"
));
if
(
!
lpath
)
return
ENOMEM
;
dpath
=
lpath
+
len
+
sizeof
(
"/lock.mdb"
);
sprintf
(
lpath
,
"%s/lock.mdb"
,
path
);
sprintf
(
dpath
,
"%s/data.mdb"
,
path
);
rc
=
mdbenv_setup_locks
(
env
,
lpath
,
mode
,
&
excl
);
if
(
rc
)
goto
leave
;
if
(
F_ISSET
(
flags
,
MDB_RDONLY
))
oflags
=
O_RDONLY
;
else
oflags
=
O_RDWR
|
O_CREAT
;
if
((
env
->
me_fd
=
open
(
dpath
,
oflags
,
mode
))
==
-
1
)
return
errno
;
if
((
rc
=
mdbenv_open2
(
env
,
flags
))
!=
MDB_SUCCESS
)
{
close
(
env
->
me_fd
);
...
...
@@ -1054,10 +1139,14 @@ mdbenv_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
}
else
{
env
->
me_path
=
strdup
(
path
);
DPRINTF
(
"opened dbenv %p"
,
(
void
*
)
env
);
pthread_key_create
(
&
env
->
me_txkey
,
mdbenv_reader_dest
);
if
(
excl
)
mdbenv_share_locks
(
env
);
}
pthread_key_create
(
&
env
->
me_txkey
,
mdbenv_reader_dest
);
leave:
free
(
lpath
);
return
rc
;
}
...
...
@@ -1074,8 +1163,10 @@ mdbenv_close(MDB_env *env)
}
close
(
env
->
me_fd
);
if
(
env
->
me_txns
)
{
shmdt
(
env
->
me_txns
);
size_t
size
=
(
env
->
me_maxreaders
-
1
)
*
sizeof
(
MDB_reader
)
+
sizeof
(
MDB_txninfo
);
munmap
(
env
->
me_txns
,
size
);
}
close
(
env
->
me_lfd
);
free
(
env
);
}
...
...
@@ -1295,7 +1386,7 @@ mdb_search_page(MDB_db *db, MDB_txn *txn, MDB_val *key,
* committed root page.
*/
if
(
txn
==
NULL
)
{
if
((
rc
=
mdbenv_read_meta
(
db
->
md_env
))
!=
MDB_SUCCESS
)
if
((
rc
=
mdbenv_read_meta
(
db
->
md_env
,
NULL
))
!=
MDB_SUCCESS
)
return
rc
;
root
=
db
->
md_env
->
me_meta
.
mm_root
;
}
else
if
(
F_ISSET
(
txn
->
mt_flags
,
MDB_TXN_ERROR
))
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment