Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
ccan
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mirror
ccan
Commits
850c5cfe
Commit
850c5cfe
authored
Mar 01, 2011
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tdb2: rework lock.c functions to return enum TDB_ERROR.
Make the other functions in lock.s return an error code, too.
parent
50b15fbd
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
228 additions
and
178 deletions
+228
-178
ccan/tdb2/check.c
ccan/tdb2/check.c
+8
-2
ccan/tdb2/free.c
ccan/tdb2/free.c
+16
-4
ccan/tdb2/hash.c
ccan/tdb2/hash.c
+26
-8
ccan/tdb2/io.c
ccan/tdb2/io.c
+5
-1
ccan/tdb2/lock.c
ccan/tdb2/lock.c
+120
-130
ccan/tdb2/private.h
ccan/tdb2/private.h
+18
-17
ccan/tdb2/summary.c
ccan/tdb2/summary.c
+8
-2
ccan/tdb2/tdb.c
ccan/tdb2/tdb.c
+9
-5
ccan/tdb2/test/run-01-new_database.c
ccan/tdb2/test/run-01-new_database.c
+1
-1
ccan/tdb2/transaction.c
ccan/tdb2/transaction.c
+17
-8
No files found.
ccan/tdb2/check.c
View file @
850c5cfe
...
...
@@ -673,11 +673,17 @@ int tdb_check(struct tdb_context *tdb,
{
tdb_off_t
*
fr
=
NULL
,
*
used
=
NULL
,
ft
,
recovery
;
size_t
num_free
=
0
,
num_used
=
0
,
num_found
=
0
,
num_ftables
=
0
;
enum
TDB_ERROR
ecode
;
if
(
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
false
)
!=
0
)
ecode
=
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
false
);
if
(
ecpde
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
if
(
tdb_lock_expand
(
tdb
,
F_RDLCK
)
!=
0
)
{
ecode
=
tdb_lock_expand
(
tdb
,
F_RDLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
tdb_allrecord_unlock
(
tdb
,
F_RDLCK
);
return
-
1
;
}
...
...
ccan/tdb2/free.c
View file @
850c5cfe
...
...
@@ -204,14 +204,18 @@ int add_free_record(struct tdb_context *tdb,
tdb_off_t
b_off
;
tdb_len_t
len
;
int
ret
;
enum
TDB_ERROR
ecode
;
assert
(
len_with_header
>=
sizeof
(
struct
tdb_free_record
));
len
=
len_with_header
-
sizeof
(
struct
tdb_used_record
);
b_off
=
bucket_off
(
tdb
->
ftable_off
,
size_to_bucket
(
len
));
if
(
tdb_lock_free_bucket
(
tdb
,
b_off
,
TDB_LOCK_WAIT
)
!=
0
)
ecode
=
tdb_lock_free_bucket
(
tdb
,
b_off
,
TDB_LOCK_WAIT
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
ret
=
enqueue_in_free
(
tdb
,
b_off
,
off
,
len
);
tdb_unlock_free_bucket
(
tdb
,
b_off
);
...
...
@@ -290,7 +294,8 @@ static int coalesce(struct tdb_context *tdb,
tdb_access_release
(
tdb
,
r
);
/* We may be violating lock order here, so best effort. */
if
(
tdb_lock_free_bucket
(
tdb
,
nb_off
,
TDB_LOCK_NOWAIT
)
==
-
1
)
{
if
(
tdb_lock_free_bucket
(
tdb
,
nb_off
,
TDB_LOCK_NOWAIT
)
!=
TDB_SUCCESS
)
{
add_stat
(
tdb
,
alloc_coalesce_lockfail
,
1
);
break
;
}
...
...
@@ -377,6 +382,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
struct
tdb_free_record
best
=
{
0
};
double
multiplier
;
size_t
size
=
adjust_size
(
keylen
,
datalen
);
enum
TDB_ERROR
ecode
;
add_stat
(
tdb
,
allocs
,
1
);
again:
...
...
@@ -384,7 +390,9 @@ again:
/* FIXME: Try non-blocking wait first, to measure contention. */
/* Lock this bucket. */
if
(
tdb_lock_free_bucket
(
tdb
,
b_off
,
TDB_LOCK_WAIT
)
==
-
1
)
{
ecode
=
tdb_lock_free_bucket
(
tdb
,
b_off
,
TDB_LOCK_WAIT
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
TDB_OFF_ERR
;
}
...
...
@@ -581,6 +589,7 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
{
uint64_t
old_size
;
tdb_len_t
wanted
;
enum
TDB_ERROR
ecode
;
/* We need room for the record header too. */
wanted
=
sizeof
(
struct
tdb_used_record
)
+
size
;
...
...
@@ -602,8 +611,11 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
wanted
=
adjust_size
(
0
,
wanted
);
/* Only one person can expand file at a time. */
if
(
tdb_lock_expand
(
tdb
,
F_WRLCK
)
!=
0
)
ecode
=
tdb_lock_expand
(
tdb
,
F_WRLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
/* Someone else may have expanded the file, so retry. */
old_size
=
tdb
->
map_size
;
...
...
ccan/tdb2/hash.c
View file @
850c5cfe
...
...
@@ -229,6 +229,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
{
uint32_t
i
,
group
;
tdb_off_t
hashtable
;
enum
TDB_ERROR
ecode
;
h
->
h
=
tdb_hash
(
tdb
,
key
.
dptr
,
key
.
dsize
);
h
->
hash_used
=
0
;
...
...
@@ -236,9 +237,12 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
h
->
home_bucket
=
use_bits
(
h
,
TDB_HASH_GROUP_BITS
);
h
->
hlock_start
=
hlock_range
(
group
,
&
h
->
hlock_range
);
if
(
tdb_lock_hashes
(
tdb
,
h
->
hlock_start
,
h
->
hlock_range
,
ltype
,
TDB_LOCK_WAIT
))
ecode
=
tdb_lock_hashes
(
tdb
,
h
->
hlock_start
,
h
->
hlock_range
,
ltype
,
TDB_LOCK_WAIT
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
TDB_OFF_ERR
;
}
hashtable
=
offsetof
(
struct
tdb_header
,
hashtable
);
if
(
tinfo
)
{
...
...
@@ -684,14 +688,18 @@ int next_in_hash(struct tdb_context *tdb,
{
const
unsigned
group_bits
=
TDB_TOPLEVEL_HASH_BITS
-
TDB_HASH_GROUP_BITS
;
tdb_off_t
hl_start
,
hl_range
,
off
;
enum
TDB_ERROR
ecode
;
while
(
tinfo
->
toplevel_group
<
(
1
<<
group_bits
))
{
hl_start
=
(
tdb_off_t
)
tinfo
->
toplevel_group
<<
(
64
-
group_bits
);
hl_range
=
1ULL
<<
group_bits
;
if
(
tdb_lock_hashes
(
tdb
,
hl_start
,
hl_range
,
F_RDLCK
,
TDB_LOCK_WAIT
)
!=
0
)
ecode
=
tdb_lock_hashes
(
tdb
,
hl_start
,
hl_range
,
F_RDLCK
,
TDB_LOCK_WAIT
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
off
=
iterate_hash
(
tdb
,
tinfo
);
if
(
off
)
{
...
...
@@ -760,7 +768,7 @@ static int chainlock(struct tdb_context *tdb, const TDB_DATA *key,
int
ltype
,
enum
tdb_lock_flags
waitflag
,
const
char
*
func
)
{
int
ret
;
enum
TDB_ERROR
ecode
;
uint64_t
h
=
tdb_hash
(
tdb
,
key
->
dptr
,
key
->
dsize
);
tdb_off_t
lockstart
,
locksize
;
unsigned
int
group
,
gbits
;
...
...
@@ -770,9 +778,13 @@ static int chainlock(struct tdb_context *tdb, const TDB_DATA *key,
lockstart
=
hlock_range
(
group
,
&
locksize
);
ret
=
tdb_lock_hashes
(
tdb
,
lockstart
,
locksize
,
ltype
,
waitflag
);
ecode
=
tdb_lock_hashes
(
tdb
,
lockstart
,
locksize
,
ltype
,
waitflag
);
tdb_trace_1rec
(
tdb
,
func
,
*
key
);
return
ret
;
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
return
0
;
}
/* lock/unlock one hash chain. This is meant to be used to reduce
...
...
@@ -787,6 +799,7 @@ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
uint64_t
h
=
tdb_hash
(
tdb
,
key
.
dptr
,
key
.
dsize
);
tdb_off_t
lockstart
,
locksize
;
unsigned
int
group
,
gbits
;
enum
TDB_ERROR
ecode
;
gbits
=
TDB_TOPLEVEL_HASH_BITS
-
TDB_HASH_GROUP_BITS
;
group
=
bits_from
(
h
,
64
-
gbits
,
gbits
);
...
...
@@ -794,5 +807,10 @@ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
lockstart
=
hlock_range
(
group
,
&
locksize
);
tdb_trace_1rec
(
tdb
,
"tdb_chainunlock"
,
key
);
return
tdb_unlock_hashes
(
tdb
,
lockstart
,
locksize
,
F_WRLCK
);
ecode
=
tdb_unlock_hashes
(
tdb
,
lockstart
,
locksize
,
F_WRLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
return
0
;
}
ccan/tdb2/io.c
View file @
850c5cfe
...
...
@@ -70,6 +70,7 @@ void tdb_mmap(struct tdb_context *tdb)
static
int
tdb_oob
(
struct
tdb_context
*
tdb
,
tdb_off_t
len
,
bool
probe
)
{
struct
stat
st
;
enum
TDB_ERROR
ecode
;
/* We can't hold pointers during this: we could unmap! */
assert
(
!
tdb
->
direct_access
...
...
@@ -89,8 +90,11 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
return
-
1
;
}
if
(
tdb_lock_expand
(
tdb
,
F_RDLCK
)
!=
0
)
ecode
=
tdb_lock_expand
(
tdb
,
F_RDLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
if
(
fstat
(
tdb
->
fd
,
&
st
)
!=
0
)
{
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
...
...
ccan/tdb2/lock.c
View file @
850c5cfe
...
...
@@ -198,21 +198,21 @@ static enum TDB_ERROR tdb_brunlock(struct tdb_context *tdb,
deadlock detection and claim a deadlock when progress can be
made. For those OSes we may loop for a while.
*/
int
tdb_allrecord_upgrade
(
struct
tdb_context
*
tdb
)
enum
TDB_ERROR
tdb_allrecord_upgrade
(
struct
tdb_context
*
tdb
)
{
int
count
=
1000
;
if
(
tdb
->
allrecord_lock
.
count
!=
1
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed: count %u too high"
,
tdb
->
allrecord_lock
.
count
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed:"
" count %u too high"
,
tdb
->
allrecord_lock
.
count
)
;
}
if
(
tdb
->
allrecord_lock
.
off
!=
1
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed: already upgraded?"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed:"
" already upgraded?"
)
;
}
while
(
count
--
)
{
...
...
@@ -222,7 +222,7 @@ int tdb_allrecord_upgrade(struct tdb_context *tdb)
TDB_LOCK_WAIT
|
TDB_LOCK_PROBE
)
==
TDB_SUCCESS
)
{
tdb
->
allrecord_lock
.
ltype
=
F_WRLCK
;
tdb
->
allrecord_lock
.
off
=
0
;
return
0
;
return
TDB_SUCCESS
;
}
if
(
errno
!=
EDEADLK
)
{
break
;
...
...
@@ -232,9 +232,8 @@ int tdb_allrecord_upgrade(struct tdb_context *tdb)
tv
.
tv_usec
=
1
;
select
(
0
,
NULL
,
NULL
,
NULL
,
&
tv
);
}
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_upgrade failed"
);
}
static
struct
tdb_lock_type
*
find_nestlock
(
struct
tdb_context
*
tdb
,
...
...
@@ -250,85 +249,86 @@ static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb,
return
NULL
;
}
int
tdb_lock_and_recover
(
struct
tdb_context
*
tdb
)
enum
TDB_ERROR
tdb_lock_and_recover
(
struct
tdb_context
*
tdb
)
{
int
ret
;
enum
TDB_ERROR
ecode
;
if
(
tdb_allrecord_lock
(
tdb
,
F_WRLCK
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
,
false
)
==
-
1
)
{
return
-
1
;
ecode
=
tdb_allrecord_lock
(
tdb
,
F_WRLCK
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
,
false
);
if
(
ecode
!=
TDB_SUCCESS
)
{
return
ecode
;
}
if
(
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
)
==
-
1
)
{
ecode
=
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb_allrecord_unlock
(
tdb
,
F_WRLCK
);
return
-
1
;
return
ecode
;
}
if
(
tdb_transaction_recover
(
tdb
)
==
-
1
)
{
ecode
=
tdb
->
ecode
;
}
ret
=
tdb_transaction_recover
(
tdb
);
tdb_unlock_open
(
tdb
);
tdb_allrecord_unlock
(
tdb
,
F_WRLCK
);
return
ret
;
return
ecode
;
}
/* lock an offset in the database. */
static
int
tdb_nest_lock
(
struct
tdb_context
*
tdb
,
tdb_off_t
offset
,
int
ltype
,
enum
tdb_lock_flags
flags
)
static
enum
TDB_ERROR
tdb_nest_lock
(
struct
tdb_context
*
tdb
,
tdb_off_t
offset
,
int
ltype
,
enum
tdb_lock_flags
flags
)
{
struct
tdb_lock_type
*
new_lck
;
enum
TDB_ERROR
ecode
;
if
(
offset
>
TDB_HASH_LOCK_START
+
TDB_HASH_LOCK_RANGE
+
tdb
->
map_size
/
8
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock: invalid offset %zu ltype=%d"
,
(
size_t
)
offset
,
ltype
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock: invalid offset %zu ltype=%d"
,
(
size_t
)
offset
,
ltype
);
}
if
(
tdb
->
flags
&
TDB_NOLOCK
)
return
0
;
return
TDB_SUCCESS
;
add_stat
(
tdb
,
locks
,
1
);
new_lck
=
find_nestlock
(
tdb
,
offset
);
if
(
new_lck
)
{
if
(
new_lck
->
ltype
==
F_RDLCK
&&
ltype
==
F_WRLCK
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock: offset %zu has read lock"
,
(
size_t
)
offset
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock:"
" offset %zu has read lock"
,
(
size_t
)
offset
)
;
}
/* Just increment the struct, posix locks don't stack. */
new_lck
->
count
++
;
return
0
;
return
TDB_SUCCESS
;
}
if
(
tdb
->
num_lockrecs
&&
offset
>=
TDB_HASH_LOCK_START
&&
offset
<
TDB_HASH_LOCK_START
+
TDB_HASH_LOCK_RANGE
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock: already have a hash lock?"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_lock: already have a hash lock?"
);
}
new_lck
=
(
struct
tdb_lock_type
*
)
realloc
(
tdb
->
lockrecs
,
sizeof
(
*
tdb
->
lockrecs
)
*
(
tdb
->
num_lockrecs
+
1
));
if
(
new_lck
==
NULL
)
{
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_nest_lock: unable to allocate %zu lock struct"
,
tdb
->
num_lockrecs
+
1
);
errno
=
ENOMEM
;
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_nest_lock:"
" unable to allocate %zu lock struct"
,
tdb
->
num_lockrecs
+
1
);
}
tdb
->
lockrecs
=
new_lck
;
/* Since fcntl locks don't nest, we do a lock for the first one,
and simply bump the count for future ones */
ecode
=
tdb_brlock
(
tdb
,
ltype
,
offset
,
1
,
flags
);
if
(
ecode
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
if
(
ecode
!=
TDB_SUCCESS
)
{
return
ecode
;
}
/* First time we grab a lock, perhaps someone died in commit? */
...
...
@@ -337,14 +337,12 @@ static int tdb_nest_lock(struct tdb_context *tdb, tdb_off_t offset, int ltype,
&&
unlikely
(
tdb_needs_recovery
(
tdb
)))
{
tdb_brunlock
(
tdb
,
ltype
,
offset
,
1
);
if
(
tdb_lock_and_recover
(
tdb
)
==
-
1
)
{
return
-
1
;
ecode
=
tdb_lock_and_recover
(
tdb
);
if
(
ecode
==
TDB_SUCCESS
)
{
ecode
=
tdb_brlock
(
tdb
,
ltype
,
offset
,
1
,
flags
);
}
ecode
=
tdb_brlock
(
tdb
,
ltype
,
offset
,
1
,
flags
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
return
ecode
;
}
}
...
...
@@ -353,27 +351,28 @@ static int tdb_nest_lock(struct tdb_context *tdb, tdb_off_t offset, int ltype,
tdb
->
lockrecs
[
tdb
->
num_lockrecs
].
ltype
=
ltype
;
tdb
->
num_lockrecs
++
;
return
0
;
return
TDB_SUCCESS
;
}
static
int
tdb_nest_unlock
(
struct
tdb_context
*
tdb
,
tdb_off_t
off
,
int
ltype
)
static
enum
TDB_ERROR
tdb_nest_unlock
(
struct
tdb_context
*
tdb
,
tdb_off_t
off
,
int
ltype
)
{
struct
tdb_lock_type
*
lck
;
enum
TDB_ERROR
ecode
;
if
(
tdb
->
flags
&
TDB_NOLOCK
)
return
0
;
return
TDB_SUCCESS
;
lck
=
find_nestlock
(
tdb
,
off
);
if
((
lck
==
NULL
)
||
(
lck
->
count
==
0
))
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_unlock: no lock for %zu"
,
(
size_t
)
off
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_nest_unlock: no lock for %zu"
,
(
size_t
)
off
)
;
}
if
(
lck
->
count
>
1
)
{
lck
->
count
--
;
return
0
;
return
TDB_SUCCESS
;
}
/*
...
...
@@ -390,17 +389,13 @@ static int tdb_nest_unlock(struct tdb_context *tdb, tdb_off_t off, int ltype)
*/
*
lck
=
tdb
->
lockrecs
[
--
tdb
->
num_lockrecs
];
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
-
1
;
}
return
0
;
return
ecode
;
}
/*
get the transaction lock
*/
int
tdb_transaction_lock
(
struct
tdb_context
*
tdb
,
int
ltype
)
enum
TDB_ERROR
tdb_transaction_lock
(
struct
tdb_context
*
tdb
,
int
ltype
)
{
return
tdb_nest_lock
(
tdb
,
TDB_TRANSACTION_LOCK
,
ltype
,
TDB_LOCK_WAIT
);
}
...
...
@@ -408,9 +403,9 @@ int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
/*
release the transaction lock
*/
int
tdb_transaction_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
)
void
tdb_transaction_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
)
{
return
tdb_nest_unlock
(
tdb
,
TDB_TRANSACTION_LOCK
,
ltype
);
tdb_nest_unlock
(
tdb
,
TDB_TRANSACTION_LOCK
,
ltype
);
}
/* We only need to lock individual bytes, but Linux merges consecutive locks
...
...
@@ -449,45 +444,43 @@ static enum TDB_ERROR tdb_lock_gradual(struct tdb_context *tdb,
/* lock/unlock entire database. It can only be upgradable if you have some
* other way of guaranteeing exclusivity (ie. transaction write lock). */
int
tdb_allrecord_lock
(
struct
tdb_context
*
tdb
,
int
ltype
,
enum
tdb_lock_flags
flags
,
bool
upgradable
)
enum
TDB_ERROR
tdb_allrecord_lock
(
struct
tdb_context
*
tdb
,
int
ltype
,
enum
tdb_lock_flags
flags
,
bool
upgradable
)
{
enum
TDB_ERROR
ecode
;
/* FIXME: There are no locks on read-only dbs */
if
(
tdb
->
read_only
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock: read-only"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock: read-only"
);
}
if
(
tdb
->
allrecord_lock
.
count
&&
(
ltype
==
F_RDLCK
||
tdb
->
allrecord_lock
.
ltype
==
F_WRLCK
))
{
tdb
->
allrecord_lock
.
count
++
;
return
0
;
return
TDB_SUCCESS
;
}
if
(
tdb
->
allrecord_lock
.
count
)
{
/* a global lock of a different type exists */
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock: already have %s lock"
,
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
?
"read"
:
"write"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock: already have %s lock"
,
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
?
"read"
:
"write"
);
}
if
(
tdb_has_hash_locks
(
tdb
))
{
/* can't combine global and chain locks */
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock: already have chain lock"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_lock:"
" already have chain lock"
)
;
}
if
(
upgradable
&&
ltype
!=
F_RDLCK
)
{
/* tdb error: you can't upgrade a write lock! */
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_lock: can't upgrade a write lock"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_lock:"
" can't upgrade a write lock"
)
;
}
add_stat
(
tdb
,
locks
,
1
);
...
...
@@ -496,12 +489,11 @@ again:
ecode
=
tdb_lock_gradual
(
tdb
,
ltype
,
flags
,
TDB_HASH_LOCK_START
,
TDB_HASH_LOCK_RANGE
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
if
(
!
(
flags
&
TDB_LOCK_PROBE
))
{
tdb_logerr
(
tdb
,
tdb
->
ecode
,
TDB_LOG_ERROR
,
tdb_logerr
(
tdb
,
ecode
,
TDB_LOG_ERROR
,
"tdb_allrecord_lock hashes failed"
);
}
return
-
1
;
return
ecode
;
}
/* Lock free tables: there to end of file. */
...
...
@@ -509,14 +501,13 @@ again:
TDB_HASH_LOCK_START
+
TDB_HASH_LOCK_RANGE
,
0
,
flags
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
if
(
!
(
flags
&
TDB_LOCK_PROBE
))
{
tdb_logerr
(
tdb
,
tdb
->
ecode
,
TDB_LOG_ERROR
,
tdb_logerr
(
tdb
,
ecode
,
TDB_LOG_ERROR
,
"tdb_allrecord_lock freetables failed"
);
}
tdb_brunlock
(
tdb
,
ltype
,
TDB_HASH_LOCK_START
,
TDB_HASH_LOCK_RANGE
);
return
-
1
;
return
ecode
;
}
tdb
->
allrecord_lock
.
count
=
1
;
...
...
@@ -528,16 +519,17 @@ again:
/* Now check for needing recovery. */
if
(
!
(
flags
&
TDB_LOCK_NOCHECK
)
&&
unlikely
(
tdb_needs_recovery
(
tdb
)))
{
tdb_allrecord_unlock
(
tdb
,
ltype
);
if
(
tdb_lock_and_recover
(
tdb
)
==
-
1
)
{
return
-
1
;
ecode
=
tdb_lock_and_recover
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
return
ecode
;
}
goto
again
;
}
return
0
;
return
TDB_SUCCESS
;
}
int
tdb_lock_open
(
struct
tdb_context
*
tdb
,
enum
tdb_lock_flags
flags
)
enum
TDB_ERROR
tdb_lock_open
(
struct
tdb_context
*
tdb
,
enum
tdb_lock_flags
flags
)
{
return
tdb_nest_lock
(
tdb
,
TDB_OPEN_LOCK
,
F_WRLCK
,
flags
);
}
...
...
@@ -552,7 +544,7 @@ bool tdb_has_open_lock(struct tdb_context *tdb)
return
find_nestlock
(
tdb
,
TDB_OPEN_LOCK
)
!=
NULL
;
}
int
tdb_lock_expand
(
struct
tdb_context
*
tdb
,
int
ltype
)
enum
TDB_ERROR
tdb_lock_expand
(
struct
tdb_context
*
tdb
,
int
ltype
)
{
/* Lock doesn't protect data, so don't check (we recurse if we do!) */
return
tdb_nest_lock
(
tdb
,
TDB_EXPANSION_LOCK
,
ltype
,
...
...
@@ -565,33 +557,33 @@ void tdb_unlock_expand(struct tdb_context *tdb, int ltype)
}
/* unlock entire db */
int
tdb_allrecord_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
)
void
tdb_allrecord_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
)
{
if
(
tdb
->
allrecord_lock
.
count
==
0
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_allrecord_unlock: not locked!"
);
return
-
1
;
return
;
}
/* Upgradable locks are marked as write locks. */
if
(
tdb
->
allrecord_lock
.
ltype
!=
ltype
&&
(
!
tdb
->
allrecord_lock
.
off
||
ltype
!=
F_RDLCK
))
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_allrecord_unlock: have %s lock"
,
"tdb_allrecord_unlock: have %s lock"
,
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
?
"read"
:
"write"
);
return
-
1
;
return
;
}
if
(
tdb
->
allrecord_lock
.
count
>
1
)
{
tdb
->
allrecord_lock
.
count
--
;
return
0
;
return
;
}
tdb
->
allrecord_lock
.
count
=
0
;
tdb
->
allrecord_lock
.
ltype
=
0
;
return
tdb_brunlock
(
tdb
,
ltype
,
TDB_HASH_LOCK_START
,
0
);
tdb_brunlock
(
tdb
,
ltype
,
TDB_HASH_LOCK_START
,
0
);
}
bool
tdb_has_expansion_lock
(
struct
tdb_context
*
tdb
)
...
...
@@ -624,10 +616,10 @@ static bool tdb_has_free_lock(struct tdb_context *tdb)
return
false
;
}
int
tdb_lock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
,
enum
tdb_lock_flags
waitflag
)
enum
TDB_ERROR
tdb_lock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
,
enum
tdb_lock_flags
waitflag
)
{
/* FIXME: Do this properly, using hlock_range */
unsigned
lock
=
TDB_HASH_LOCK_START
...
...
@@ -636,35 +628,34 @@ int tdb_lock_hashes(struct tdb_context *tdb,
/* a allrecord lock allows us to avoid per chain locks */
if
(
tdb
->
allrecord_lock
.
count
&&
(
ltype
==
tdb
->
allrecord_lock
.
ltype
||
ltype
==
F_RDLCK
))
{
return
0
;
return
TDB_SUCCESS
;
}
if
(
tdb
->
allrecord_lock
.
count
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_lock_hashes: already have %s allrecordlock"
,
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
?
"read"
:
"write"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_USE_ERROR
,
"tdb_lock_hashes:"
" already have %s allrecordlock"
,
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
?
"read"
:
"write"
)
;
}
if
(
tdb_has_free_lock
(
tdb
))
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_hashes: already have free lock"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_hashes: already have free lock"
);
}
if
(
tdb_has_expansion_lock
(
tdb
))
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_hashes: already have expansion lock"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_hashes:"
" already have expansion lock"
)
;
}
return
tdb_nest_lock
(
tdb
,
lock
,
ltype
,
waitflag
);
}
int
tdb_unlock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
)
enum
TDB_ERROR
tdb_unlock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
)
{
unsigned
lock
=
TDB_HASH_LOCK_START
+
(
hash_lock
>>
(
64
-
TDB_HASH_LOCK_RANGE_BITS
));
...
...
@@ -673,11 +664,10 @@ int tdb_unlock_hashes(struct tdb_context *tdb,
if
(
tdb
->
allrecord_lock
.
count
)
{
if
(
tdb
->
allrecord_lock
.
ltype
==
F_RDLCK
&&
ltype
==
F_WRLCK
)
{
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_unlock_hashes RO allrecord!"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_unlock_hashes RO allrecord!"
);
}
return
0
;
return
TDB_SUCCESS
;
}
return
tdb_nest_unlock
(
tdb
,
lock
,
ltype
);
...
...
@@ -694,8 +684,8 @@ static tdb_off_t free_lock_off(tdb_off_t b_off)
+
b_off
/
sizeof
(
tdb_off_t
);
}
int
tdb_lock_free_bucket
(
struct
tdb_context
*
tdb
,
tdb_off_t
b_off
,
enum
tdb_lock_flags
waitflag
)
enum
TDB_ERROR
tdb_lock_free_bucket
(
struct
tdb_context
*
tdb
,
tdb_off_t
b_off
,
enum
tdb_lock_flags
waitflag
)
{
assert
(
b_off
>=
sizeof
(
struct
tdb_header
));
...
...
@@ -703,16 +693,16 @@ int tdb_lock_free_bucket(struct tdb_context *tdb, tdb_off_t b_off,
if
(
tdb
->
allrecord_lock
.
count
)
{
if
(
tdb
->
allrecord_lock
.
ltype
==
F_WRLCK
)
return
0
;
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_free_bucket with RO allrecordlock!"
);
return
-
1
;
return
tdb_logerr
(
tdb
,
TDB_ERR_LOCK
,
TDB_LOG_ERROR
,
"tdb_lock_free_bucket with"
" read-only allrecordlock!"
)
;
}
#if 0 /* FIXME */
if (tdb_has_expansion_lock(tdb)) {
tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
"tdb_lock_free_bucket: already have expansion lock");
return -1
;
return
tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
"tdb_lock_free_bucket:"
" already have expansion lock")
;
}
#endif
...
...
ccan/tdb2/private.h
View file @
850c5cfe
...
...
@@ -518,43 +518,44 @@ void add_stat_(struct tdb_context *tdb, uint64_t *stat, size_t val);
void
tdb_lock_init
(
struct
tdb_context
*
tdb
);
/* Lock/unlock a range of hashes. */
int
tdb_lock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
,
enum
tdb_lock_flags
waitflag
);
int
tdb_unlock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
);
enum
TDB_ERROR
tdb_lock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
,
enum
tdb_lock_flags
waitflag
);
enum
TDB_ERROR
tdb_unlock_hashes
(
struct
tdb_context
*
tdb
,
tdb_off_t
hash_lock
,
tdb_len_t
hash_range
,
int
ltype
);
/* Lock/unlock a particular free bucket. */
int
tdb_lock_free_bucket
(
struct
tdb_context
*
tdb
,
tdb_off_t
b_off
,
enum
tdb_lock_flags
waitflag
);
enum
TDB_ERROR
tdb_lock_free_bucket
(
struct
tdb_context
*
tdb
,
tdb_off_t
b_off
,
enum
tdb_lock_flags
waitflag
);
void
tdb_unlock_free_bucket
(
struct
tdb_context
*
tdb
,
tdb_off_t
b_off
);
/* Serialize transaction start. */
int
tdb_transaction_lock
(
struct
tdb_context
*
tdb
,
int
ltype
);
int
tdb_transaction_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
);
enum
TDB_ERROR
tdb_transaction_lock
(
struct
tdb_context
*
tdb
,
int
ltype
);
void
tdb_transaction_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
);
/* Do we have any hash locks (ie. via tdb_chainlock) ? */
bool
tdb_has_hash_locks
(
struct
tdb_context
*
tdb
);
/* Lock entire database. */
int
tdb_allrecord_lock
(
struct
tdb_context
*
tdb
,
int
ltype
,
enum
tdb_lock_flags
flags
,
bool
upgradable
);
int
tdb_allrecord_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
);
int
tdb_allrecord_upgrade
(
struct
tdb_context
*
tdb
);
enum
TDB_ERROR
tdb_allrecord_lock
(
struct
tdb_context
*
tdb
,
int
ltype
,
enum
tdb_lock_flags
flags
,
bool
upgradable
);
void
tdb_allrecord_unlock
(
struct
tdb_context
*
tdb
,
int
ltype
);
enum
TDB_ERROR
tdb_allrecord_upgrade
(
struct
tdb_context
*
tdb
);
/* Serialize db open. */
int
tdb_lock_open
(
struct
tdb_context
*
tdb
,
enum
tdb_lock_flags
flags
);
enum
TDB_ERROR
tdb_lock_open
(
struct
tdb_context
*
tdb
,
enum
tdb_lock_flags
flags
);
void
tdb_unlock_open
(
struct
tdb_context
*
tdb
);
bool
tdb_has_open_lock
(
struct
tdb_context
*
tdb
);
/* Serialize db expand. */
int
tdb_lock_expand
(
struct
tdb_context
*
tdb
,
int
ltype
);
enum
TDB_ERROR
tdb_lock_expand
(
struct
tdb_context
*
tdb
,
int
ltype
);
void
tdb_unlock_expand
(
struct
tdb_context
*
tdb
,
int
ltype
);
bool
tdb_has_expansion_lock
(
struct
tdb_context
*
tdb
);
/* If it needs recovery, grab all the locks and do it. */
int
tdb_lock_and_recover
(
struct
tdb_context
*
tdb
);
enum
TDB_ERROR
tdb_lock_and_recover
(
struct
tdb_context
*
tdb
);
/* transaction.c: */
int
tdb_transaction_recover
(
struct
tdb_context
*
tdb
);
...
...
ccan/tdb2/summary.c
View file @
850c5cfe
...
...
@@ -152,13 +152,19 @@ char *tdb_summary(struct tdb_context *tdb, enum tdb_summary_flags flags)
*
buckets
,
*
chains
;
char
*
hashesg
,
*
freeg
,
*
keysg
,
*
datag
,
*
extrag
,
*
uncoalg
,
*
bucketsg
;
char
*
ret
=
NULL
;
enum
TDB_ERROR
ecode
;
hashesg
=
freeg
=
keysg
=
datag
=
extrag
=
uncoalg
=
bucketsg
=
NULL
;
if
(
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
false
)
!=
0
)
ecode
=
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
false
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
return
NULL
;
}
if
(
tdb_lock_expand
(
tdb
,
F_RDLCK
)
!=
0
)
{
ecode
=
tdb_lock_expand
(
tdb
,
F_RDLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
tdb_allrecord_unlock
(
tdb
,
F_RDLCK
);
return
NULL
;
}
...
...
ccan/tdb2/tdb.c
View file @
850c5cfe
...
...
@@ -173,6 +173,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
ssize_t
rlen
;
struct
tdb_header
hdr
;
struct
tdb_attribute_seed
*
seed
=
NULL
;
enum
TDB_ERROR
ecode
;
tdb
=
malloc
(
sizeof
(
*
tdb
));
if
(
!
tdb
)
{
...
...
@@ -265,9 +266,8 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
fcntl
(
tdb
->
fd
,
F_SETFD
,
v
|
FD_CLOEXEC
);
/* ensure there is only one process initialising at once */
if
(
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
)
==
-
1
)
{
/* errno set by tdb_brlock */
saved_errno
=
errno
;
tdb
->
ecode
=
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
);
if
(
tdb
->
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
...
...
@@ -346,8 +346,12 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
tdb
->
methods
->
oob
(
tdb
,
tdb
->
map_size
+
1
,
true
);
/* Now it's fully formed, recover if necessary. */
if
(
tdb_needs_recovery
(
tdb
)
&&
tdb_lock_and_recover
(
tdb
)
==
-
1
)
{
goto
fail
;
if
(
tdb_needs_recovery
(
tdb
))
{
ecode
=
tdb_lock_and_recover
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
goto
fail
;
}
}
if
(
tdb_ftable_init
(
tdb
)
==
-
1
)
...
...
ccan/tdb2/test/run-01-new_database.c
View file @
850c5cfe
...
...
@@ -11,7 +11,7 @@
#include "logging.h"
/* FIXME: Check these! */
#define INITIAL_TDB_MALLOC "tdb.c", 17
7
, FAILTEST_MALLOC
#define INITIAL_TDB_MALLOC "tdb.c", 17
8
, FAILTEST_MALLOC
#define LOGGING_MALLOC "tdb.c", 734, FAILTEST_MALLOC
#define URANDOM_OPEN "tdb.c", 49, FAILTEST_OPEN
#define URANDOM_READ "tdb.c", 29, FAILTEST_READ
...
...
ccan/tdb2/transaction.c
View file @
850c5cfe
...
...
@@ -499,6 +499,8 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
*/
int
tdb_transaction_start
(
struct
tdb_context
*
tdb
)
{
enum
TDB_ERROR
ecode
;
/* some sanity checks */
if
(
tdb
->
read_only
||
(
tdb
->
flags
&
TDB_INTERNAL
))
{
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
...
...
@@ -536,7 +538,9 @@ int tdb_transaction_start(struct tdb_context *tdb)
/* get the transaction write lock. This is a blocking lock. As
discussed with Volker, there are a number of ways we could
make this async, which we will probably do in the future */
if
(
tdb_transaction_lock
(
tdb
,
F_WRLCK
)
==
-
1
)
{
ecode
=
tdb_transaction_lock
(
tdb
,
F_WRLCK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
SAFE_FREE
(
tdb
->
transaction
->
blocks
);
SAFE_FREE
(
tdb
->
transaction
);
return
-
1
;
...
...
@@ -544,7 +548,9 @@ int tdb_transaction_start(struct tdb_context *tdb)
/* get a read lock over entire file. This is upgraded to a write
lock during the commit */
if
(
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
true
)
==
-
1
)
{
ecode
=
tdb_allrecord_lock
(
tdb
,
F_RDLCK
,
TDB_LOCK_WAIT
,
true
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb
->
ecode
=
ecode
;
goto
fail_allrecord_lock
;
}
...
...
@@ -853,6 +859,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
static
int
_tdb_transaction_prepare_commit
(
struct
tdb_context
*
tdb
)
{
const
struct
tdb_methods
*
methods
;
enum
TDB_ERROR
ecode
;
if
(
tdb
->
transaction
==
NULL
)
{
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
...
...
@@ -890,8 +897,9 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb)
methods
=
tdb
->
transaction
->
io_methods
;
/* upgrade the main transaction lock region to a write lock */
if
(
tdb_allrecord_upgrade
(
tdb
)
==
-
1
)
{
tdb_logerr
(
tdb
,
tdb
->
ecode
,
TDB_LOG_ERROR
,
ecode
=
tdb_allrecord_upgrade
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb_logerr
(
tdb
,
ecode
,
TDB_LOG_ERROR
,
"tdb_transaction_prepare_commit:"
" failed to upgrade hash locks"
);
_tdb_transaction_cancel
(
tdb
);
...
...
@@ -900,10 +908,11 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb)
/* get the open lock - this prevents new users attaching to the database
during the commit */
if
(
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
)
==
-
1
)
{
tdb_logerr
(
tdb
,
tdb
->
ecode
,
TDB_LOG_ERROR
,
"tdb_transaction_prepare_commit:"
" failed to get open lock"
);
ecode
=
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
tdb_logerr
(
tdb
,
ecode
,
TDB_LOG_ERROR
,
"tdb_transaction_prepare_commit:"
" failed to get open lock"
);
_tdb_transaction_cancel
(
tdb
);
return
-
1
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a 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