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
efdf0f2d
Commit
efdf0f2d
authored
Mar 17, 2011
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tdb2: move open routines into a separate file (open.c)
Simply tidying up.
parent
9d9a9897
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
511 additions
and
483 deletions
+511
-483
ccan/tdb2/open.c
ccan/tdb2/open.c
+479
-0
ccan/tdb2/tdb.c
ccan/tdb2/tdb.c
+0
-480
ccan/tdb2/test/failtest_helper.h
ccan/tdb2/test/failtest_helper.h
+3
-3
ccan/tdb2/test/run-001-encode.c
ccan/tdb2/test/run-001-encode.c
+1
-0
ccan/tdb2/test/run-001-fls.c
ccan/tdb2/test/run-001-fls.c
+1
-0
ccan/tdb2/test/run-01-new_database.c
ccan/tdb2/test/run-01-new_database.c
+1
-0
ccan/tdb2/test/run-02-expand.c
ccan/tdb2/test/run-02-expand.c
+1
-0
ccan/tdb2/test/run-03-coalesce.c
ccan/tdb2/test/run-03-coalesce.c
+1
-0
ccan/tdb2/test/run-04-basichash.c
ccan/tdb2/test/run-04-basichash.c
+1
-0
ccan/tdb2/test/run-10-simple-store.c
ccan/tdb2/test/run-10-simple-store.c
+1
-0
ccan/tdb2/test/run-11-simple-fetch.c
ccan/tdb2/test/run-11-simple-fetch.c
+1
-0
ccan/tdb2/test/run-12-store.c
ccan/tdb2/test/run-12-store.c
+1
-0
ccan/tdb2/test/run-13-delete.c
ccan/tdb2/test/run-13-delete.c
+1
-0
ccan/tdb2/test/run-15-append.c
ccan/tdb2/test/run-15-append.c
+1
-0
ccan/tdb2/test/run-20-growhash.c
ccan/tdb2/test/run-20-growhash.c
+1
-0
ccan/tdb2/test/run-25-hashoverload.c
ccan/tdb2/test/run-25-hashoverload.c
+1
-0
ccan/tdb2/test/run-30-exhaust-before-expand.c
ccan/tdb2/test/run-30-exhaust-before-expand.c
+1
-0
ccan/tdb2/test/run-50-multiple-freelists.c
ccan/tdb2/test/run-50-multiple-freelists.c
+1
-0
ccan/tdb2/test/run-55-transaction.c
ccan/tdb2/test/run-55-transaction.c
+1
-0
ccan/tdb2/test/run-56-open-during-transaction.c
ccan/tdb2/test/run-56-open-during-transaction.c
+1
-0
ccan/tdb2/test/run-57-die-during-transaction.c
ccan/tdb2/test/run-57-die-during-transaction.c
+1
-0
ccan/tdb2/test/run-add-remove-flags.c
ccan/tdb2/test/run-add-remove-flags.c
+1
-0
ccan/tdb2/test/run-features.c
ccan/tdb2/test/run-features.c
+1
-0
ccan/tdb2/test/run-firstkey-nextkey.c
ccan/tdb2/test/run-firstkey-nextkey.c
+1
-0
ccan/tdb2/test/run-missing-entries.c
ccan/tdb2/test/run-missing-entries.c
+1
-0
ccan/tdb2/test/run-record-expand.c
ccan/tdb2/test/run-record-expand.c
+1
-0
ccan/tdb2/test/run-remap-in-read_traverse.c
ccan/tdb2/test/run-remap-in-read_traverse.c
+1
-0
ccan/tdb2/test/run-seed.c
ccan/tdb2/test/run-seed.c
+1
-0
ccan/tdb2/test/run-simple-delete.c
ccan/tdb2/test/run-simple-delete.c
+1
-0
ccan/tdb2/test/run-summary.c
ccan/tdb2/test/run-summary.c
+1
-0
ccan/tdb2/test/run-tdb_errorstr.c
ccan/tdb2/test/run-tdb_errorstr.c
+1
-0
ccan/tdb2/test/run-traverse.c
ccan/tdb2/test/run-traverse.c
+1
-0
No files found.
ccan/tdb2/open.c
0 → 100644
View file @
efdf0f2d
#include "private.h"
/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
static
struct
tdb_context
*
tdbs
=
NULL
;
static
bool
tdb_already_open
(
dev_t
device
,
ino_t
ino
)
{
struct
tdb_context
*
i
;
for
(
i
=
tdbs
;
i
;
i
=
i
->
next
)
{
if
(
i
->
device
==
device
&&
i
->
inode
==
ino
)
{
return
true
;
}
}
return
false
;
}
static
bool
read_all
(
int
fd
,
void
*
buf
,
size_t
len
)
{
while
(
len
)
{
ssize_t
ret
;
ret
=
read
(
fd
,
buf
,
len
);
if
(
ret
<
0
)
return
false
;
if
(
ret
==
0
)
{
/* ETOOSHORT? */
errno
=
EWOULDBLOCK
;
return
false
;
}
buf
=
(
char
*
)
buf
+
ret
;
len
-=
ret
;
}
return
true
;
}
static
uint64_t
random_number
(
struct
tdb_context
*
tdb
)
{
int
fd
;
uint64_t
ret
=
0
;
struct
timeval
now
;
fd
=
open
(
"/dev/urandom"
,
O_RDONLY
);
if
(
fd
>=
0
)
{
if
(
read_all
(
fd
,
&
ret
,
sizeof
(
ret
)))
{
close
(
fd
);
return
ret
;
}
close
(
fd
);
}
/* FIXME: Untested! Based on Wikipedia protocol description! */
fd
=
open
(
"/dev/egd-pool"
,
O_RDWR
);
if
(
fd
>=
0
)
{
/* Command is 1, next byte is size we want to read. */
char
cmd
[
2
]
=
{
1
,
sizeof
(
uint64_t
)
};
if
(
write
(
fd
,
cmd
,
sizeof
(
cmd
))
==
sizeof
(
cmd
))
{
char
reply
[
1
+
sizeof
(
uint64_t
)];
int
r
=
read
(
fd
,
reply
,
sizeof
(
reply
));
if
(
r
>
1
)
{
/* Copy at least some bytes. */
memcpy
(
&
ret
,
reply
+
1
,
r
-
1
);
if
(
reply
[
0
]
==
sizeof
(
uint64_t
)
&&
r
==
sizeof
(
reply
))
{
close
(
fd
);
return
ret
;
}
}
}
close
(
fd
);
}
/* Fallback: pid and time. */
gettimeofday
(
&
now
,
NULL
);
ret
=
getpid
()
*
100132289ULL
+
now
.
tv_sec
*
1000000ULL
+
now
.
tv_usec
;
tdb_logerr
(
tdb
,
TDB_SUCCESS
,
TDB_LOG_WARNING
,
"tdb_open: random from getpid and time"
);
return
ret
;
}
struct
new_database
{
struct
tdb_header
hdr
;
struct
tdb_freetable
ftable
;
};
/* initialise a new database */
static
enum
TDB_ERROR
tdb_new_database
(
struct
tdb_context
*
tdb
,
struct
tdb_attribute_seed
*
seed
,
struct
tdb_header
*
hdr
)
{
/* We make it up in memory, then write it out if not internal */
struct
new_database
newdb
;
unsigned
int
magic_len
;
ssize_t
rlen
;
enum
TDB_ERROR
ecode
;
/* Fill in the header */
newdb
.
hdr
.
version
=
TDB_VERSION
;
if
(
seed
)
newdb
.
hdr
.
hash_seed
=
seed
->
seed
;
else
newdb
.
hdr
.
hash_seed
=
random_number
(
tdb
);
newdb
.
hdr
.
hash_test
=
TDB_HASH_MAGIC
;
newdb
.
hdr
.
hash_test
=
tdb
->
khash
(
&
newdb
.
hdr
.
hash_test
,
sizeof
(
newdb
.
hdr
.
hash_test
),
newdb
.
hdr
.
hash_seed
,
tdb
->
hash_priv
);
newdb
.
hdr
.
recovery
=
0
;
newdb
.
hdr
.
features_used
=
newdb
.
hdr
.
features_offered
=
TDB_FEATURE_MASK
;
memset
(
newdb
.
hdr
.
reserved
,
0
,
sizeof
(
newdb
.
hdr
.
reserved
));
/* Initial hashes are empty. */
memset
(
newdb
.
hdr
.
hashtable
,
0
,
sizeof
(
newdb
.
hdr
.
hashtable
));
/* Free is empty. */
newdb
.
hdr
.
free_table
=
offsetof
(
struct
new_database
,
ftable
);
memset
(
&
newdb
.
ftable
,
0
,
sizeof
(
newdb
.
ftable
));
ecode
=
set_header
(
NULL
,
&
newdb
.
ftable
.
hdr
,
TDB_FTABLE_MAGIC
,
0
,
sizeof
(
newdb
.
ftable
)
-
sizeof
(
newdb
.
ftable
.
hdr
),
sizeof
(
newdb
.
ftable
)
-
sizeof
(
newdb
.
ftable
.
hdr
),
0
);
if
(
ecode
!=
TDB_SUCCESS
)
{
return
ecode
;
}
/* Magic food */
memset
(
newdb
.
hdr
.
magic_food
,
0
,
sizeof
(
newdb
.
hdr
.
magic_food
));
strcpy
(
newdb
.
hdr
.
magic_food
,
TDB_MAGIC_FOOD
);
/* This creates an endian-converted database, as if read from disk */
magic_len
=
sizeof
(
newdb
.
hdr
.
magic_food
);
tdb_convert
(
tdb
,
(
char
*
)
&
newdb
.
hdr
+
magic_len
,
sizeof
(
newdb
)
-
magic_len
);
*
hdr
=
newdb
.
hdr
;
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
tdb
->
map_size
=
sizeof
(
newdb
);
tdb
->
map_ptr
=
malloc
(
tdb
->
map_size
);
if
(
!
tdb
->
map_ptr
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to allocate"
);
}
memcpy
(
tdb
->
map_ptr
,
&
newdb
,
tdb
->
map_size
);
return
TDB_SUCCESS
;
}
if
(
lseek
(
tdb
->
fd
,
0
,
SEEK_SET
)
==
-
1
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to seek: %s"
,
strerror
(
errno
));
}
if
(
ftruncate
(
tdb
->
fd
,
0
)
==
-
1
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to truncate: %s"
,
strerror
(
errno
));
}
rlen
=
write
(
tdb
->
fd
,
&
newdb
,
sizeof
(
newdb
));
if
(
rlen
!=
sizeof
(
newdb
))
{
if
(
rlen
>=
0
)
errno
=
ENOSPC
;
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database: %zi writing header: %s"
,
rlen
,
strerror
(
errno
));
}
return
TDB_SUCCESS
;
}
struct
tdb_context
*
tdb_open
(
const
char
*
name
,
int
tdb_flags
,
int
open_flags
,
mode_t
mode
,
union
tdb_attribute
*
attr
)
{
struct
tdb_context
*
tdb
;
struct
stat
st
;
int
saved_errno
=
0
;
uint64_t
hash_test
;
unsigned
v
;
ssize_t
rlen
;
struct
tdb_header
hdr
;
struct
tdb_attribute_seed
*
seed
=
NULL
;
tdb_bool_err
berr
;
enum
TDB_ERROR
ecode
;
tdb
=
malloc
(
sizeof
(
*
tdb
));
if
(
!
tdb
)
{
/* Can't log this */
errno
=
ENOMEM
;
return
NULL
;
}
tdb
->
name
=
NULL
;
tdb
->
map_ptr
=
NULL
;
tdb
->
direct_access
=
0
;
tdb
->
fd
=
-
1
;
tdb
->
map_size
=
sizeof
(
struct
tdb_header
);
tdb
->
flags
=
tdb_flags
;
tdb
->
logfn
=
NULL
;
tdb
->
transaction
=
NULL
;
tdb
->
stats
=
NULL
;
tdb
->
access
=
NULL
;
tdb_hash_init
(
tdb
);
tdb_io_init
(
tdb
);
tdb_lock_init
(
tdb
);
while
(
attr
)
{
switch
(
attr
->
base
.
attr
)
{
case
TDB_ATTRIBUTE_LOG
:
tdb
->
logfn
=
attr
->
log
.
log_fn
;
tdb
->
log_private
=
attr
->
log
.
log_private
;
break
;
case
TDB_ATTRIBUTE_HASH
:
tdb
->
khash
=
attr
->
hash
.
hash_fn
;
tdb
->
hash_priv
=
attr
->
hash
.
hash_private
;
break
;
case
TDB_ATTRIBUTE_SEED
:
seed
=
&
attr
->
seed
;
break
;
case
TDB_ATTRIBUTE_STATS
:
tdb
->
stats
=
&
attr
->
stats
;
/* They have stats we don't know about? Tell them. */
if
(
tdb
->
stats
->
size
>
sizeof
(
attr
->
stats
))
tdb
->
stats
->
size
=
sizeof
(
attr
->
stats
);
break
;
default:
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open:"
" unknown attribute type %u"
,
attr
->
base
.
attr
);
goto
fail
;
}
attr
=
attr
->
base
.
next
;
}
if
(
tdb_flags
&
~
(
TDB_INTERNAL
|
TDB_NOLOCK
|
TDB_NOMMAP
|
TDB_CONVERT
|
TDB_NOSYNC
))
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open: unknown flags %u"
,
tdb_flags
);
goto
fail
;
}
if
((
open_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open: can't open tdb %s write-only"
,
name
);
goto
fail
;
}
if
((
open_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
tdb
->
read_only
=
true
;
tdb
->
mmap_flags
=
PROT_READ
;
}
else
{
tdb
->
read_only
=
false
;
tdb
->
mmap_flags
=
PROT_READ
|
PROT_WRITE
;
}
/* internal databases don't need any of the rest. */
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
tdb
->
flags
|=
(
TDB_NOLOCK
|
TDB_NOMMAP
);
ecode
=
tdb_new_database
(
tdb
,
seed
,
&
hdr
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
tdb_convert
(
tdb
,
&
hdr
.
hash_seed
,
sizeof
(
hdr
.
hash_seed
));
tdb
->
hash_seed
=
hdr
.
hash_seed
;
tdb_ftable_init
(
tdb
);
return
tdb
;
}
if
((
tdb
->
fd
=
open
(
name
,
open_flags
,
mode
))
==
-
1
)
{
/* errno set by open(2) */
saved_errno
=
errno
;
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: could not open file %s: %s"
,
name
,
strerror
(
errno
));
goto
fail
;
}
/* on exec, don't inherit the fd */
v
=
fcntl
(
tdb
->
fd
,
F_GETFD
,
0
);
fcntl
(
tdb
->
fd
,
F_SETFD
,
v
|
FD_CLOEXEC
);
/* ensure there is only one process initialising at once */
ecode
=
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
/* If they used O_TRUNC, read will return 0. */
rlen
=
read
(
tdb
->
fd
,
&
hdr
,
sizeof
(
hdr
));
if
(
rlen
==
0
&&
(
open_flags
&
O_CREAT
))
{
ecode
=
tdb_new_database
(
tdb
,
seed
,
&
hdr
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
}
else
if
(
rlen
<
0
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: error %s reading %s"
,
strerror
(
errno
),
name
);
goto
fail
;
}
else
if
(
rlen
<
sizeof
(
hdr
)
||
strcmp
(
hdr
.
magic_food
,
TDB_MAGIC_FOOD
)
!=
0
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: %s is not a tdb file"
,
name
);
goto
fail
;
}
if
(
hdr
.
version
!=
TDB_VERSION
)
{
if
(
hdr
.
version
==
bswap_64
(
TDB_VERSION
))
tdb
->
flags
|=
TDB_CONVERT
;
else
{
/* wrong version */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open:"
" %s is unknown version 0x%llx"
,
name
,
(
long
long
)
hdr
.
version
);
goto
fail
;
}
}
tdb_convert
(
tdb
,
&
hdr
,
sizeof
(
hdr
));
tdb
->
hash_seed
=
hdr
.
hash_seed
;
hash_test
=
TDB_HASH_MAGIC
;
hash_test
=
tdb_hash
(
tdb
,
&
hash_test
,
sizeof
(
hash_test
));
if
(
hdr
.
hash_test
!=
hash_test
)
{
/* wrong hash variant */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open:"
" %s uses a different hash function"
,
name
);
goto
fail
;
}
if
(
fstat
(
tdb
->
fd
,
&
st
)
==
-
1
)
{
saved_errno
=
errno
;
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: could not stat open %s: %s"
,
name
,
strerror
(
errno
));
goto
fail
;
}
/* Is it already in the open list? If so, fail. */
if
(
tdb_already_open
(
st
.
st_dev
,
st
.
st_ino
))
{
/* FIXME */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_USE_ERROR
,
"tdb_open: %s (%d,%d) is already open"
" in this process"
,
name
,
(
int
)
st
.
st_dev
,
(
int
)
st
.
st_ino
);
goto
fail
;
}
tdb
->
name
=
strdup
(
name
);
if
(
!
tdb
->
name
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_open: failed to allocate name"
);
goto
fail
;
}
/* Clear any features we don't understand. */
if
((
open_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
hdr
.
features_used
&=
TDB_FEATURE_MASK
;
if
(
tdb_write_convert
(
tdb
,
offsetof
(
struct
tdb_header
,
features_used
),
&
hdr
.
features_used
,
sizeof
(
hdr
.
features_used
))
==
-
1
)
goto
fail
;
}
tdb
->
device
=
st
.
st_dev
;
tdb
->
inode
=
st
.
st_ino
;
tdb_unlock_open
(
tdb
);
/* This make sure we have current map_size and mmap. */
tdb
->
methods
->
oob
(
tdb
,
tdb
->
map_size
+
1
,
true
);
/* Now it's fully formed, recover if necessary. */
berr
=
tdb_needs_recovery
(
tdb
);
if
(
unlikely
(
berr
!=
false
))
{
if
(
berr
<
0
)
{
ecode
=
berr
;
goto
fail
;
}
ecode
=
tdb_lock_and_recover
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
}
ecode
=
tdb_ftable_init
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
tdb
->
next
=
tdbs
;
tdbs
=
tdb
;
return
tdb
;
fail:
/* Map ecode to some logical errno. */
if
(
!
saved_errno
)
{
switch
(
ecode
)
{
case
TDB_ERR_CORRUPT
:
case
TDB_ERR_IO
:
saved_errno
=
EIO
;
break
;
case
TDB_ERR_LOCK
:
saved_errno
=
EWOULDBLOCK
;
break
;
case
TDB_ERR_OOM
:
saved_errno
=
ENOMEM
;
break
;
case
TDB_ERR_EINVAL
:
saved_errno
=
EINVAL
;
break
;
default:
saved_errno
=
EINVAL
;
break
;
}
}
#ifdef TDB_TRACE
close
(
tdb
->
tracefd
);
#endif
if
(
tdb
->
map_ptr
)
{
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
free
(
tdb
->
map_ptr
);
}
else
tdb_munmap
(
tdb
);
}
free
(
tdb
->
lockrecs
);
free
((
char
*
)
tdb
->
name
);
if
(
tdb
->
fd
!=
-
1
)
if
(
close
(
tdb
->
fd
)
!=
0
)
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: failed to close tdb->fd"
" on error: %s"
,
strerror
(
errno
));
free
(
tdb
);
errno
=
saved_errno
;
return
NULL
;
}
int
tdb_close
(
struct
tdb_context
*
tdb
)
{
struct
tdb_context
**
i
;
int
ret
=
0
;
tdb_trace
(
tdb
,
"tdb_close"
);
if
(
tdb
->
transaction
)
{
tdb_transaction_cancel
(
tdb
);
}
if
(
tdb
->
map_ptr
)
{
if
(
tdb
->
flags
&
TDB_INTERNAL
)
free
(
tdb
->
map_ptr
);
else
tdb_munmap
(
tdb
);
}
free
((
char
*
)
tdb
->
name
);
if
(
tdb
->
fd
!=
-
1
)
{
ret
=
close
(
tdb
->
fd
);
tdb
->
fd
=
-
1
;
}
free
(
tdb
->
lockrecs
);
/* Remove from contexts list */
for
(
i
=
&
tdbs
;
*
i
;
i
=
&
(
*
i
)
->
next
)
{
if
(
*
i
==
tdb
)
{
*
i
=
tdb
->
next
;
break
;
}
}
#ifdef TDB_TRACE
close
(
tdb
->
tracefd
);
#endif
free
(
tdb
);
return
ret
;
}
ccan/tdb2/tdb.c
View file @
efdf0f2d
#include "private.h"
#include "private.h"
#include <ccan/asprintf/asprintf.h>
#include <ccan/asprintf/asprintf.h>
#include <ccan/tdb2/tdb2.h>
#include <assert.h>
#include <stdarg.h>
#include <stdarg.h>
/* The null return. */
/* The null return. */
struct
tdb_data
tdb_null
=
{
.
dptr
=
NULL
,
.
dsize
=
0
};
struct
tdb_data
tdb_null
=
{
.
dptr
=
NULL
,
.
dsize
=
0
};
/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
static
struct
tdb_context
*
tdbs
=
NULL
;
static
bool
tdb_already_open
(
dev_t
device
,
ino_t
ino
)
{
struct
tdb_context
*
i
;
for
(
i
=
tdbs
;
i
;
i
=
i
->
next
)
{
if
(
i
->
device
==
device
&&
i
->
inode
==
ino
)
{
return
true
;
}
}
return
false
;
}
static
bool
read_all
(
int
fd
,
void
*
buf
,
size_t
len
)
{
while
(
len
)
{
ssize_t
ret
;
ret
=
read
(
fd
,
buf
,
len
);
if
(
ret
<
0
)
return
false
;
if
(
ret
==
0
)
{
/* ETOOSHORT? */
errno
=
EWOULDBLOCK
;
return
false
;
}
buf
=
(
char
*
)
buf
+
ret
;
len
-=
ret
;
}
return
true
;
}
static
uint64_t
random_number
(
struct
tdb_context
*
tdb
)
{
int
fd
;
uint64_t
ret
=
0
;
struct
timeval
now
;
fd
=
open
(
"/dev/urandom"
,
O_RDONLY
);
if
(
fd
>=
0
)
{
if
(
read_all
(
fd
,
&
ret
,
sizeof
(
ret
)))
{
close
(
fd
);
return
ret
;
}
close
(
fd
);
}
/* FIXME: Untested! Based on Wikipedia protocol description! */
fd
=
open
(
"/dev/egd-pool"
,
O_RDWR
);
if
(
fd
>=
0
)
{
/* Command is 1, next byte is size we want to read. */
char
cmd
[
2
]
=
{
1
,
sizeof
(
uint64_t
)
};
if
(
write
(
fd
,
cmd
,
sizeof
(
cmd
))
==
sizeof
(
cmd
))
{
char
reply
[
1
+
sizeof
(
uint64_t
)];
int
r
=
read
(
fd
,
reply
,
sizeof
(
reply
));
if
(
r
>
1
)
{
/* Copy at least some bytes. */
memcpy
(
&
ret
,
reply
+
1
,
r
-
1
);
if
(
reply
[
0
]
==
sizeof
(
uint64_t
)
&&
r
==
sizeof
(
reply
))
{
close
(
fd
);
return
ret
;
}
}
}
close
(
fd
);
}
/* Fallback: pid and time. */
gettimeofday
(
&
now
,
NULL
);
ret
=
getpid
()
*
100132289ULL
+
now
.
tv_sec
*
1000000ULL
+
now
.
tv_usec
;
tdb_logerr
(
tdb
,
TDB_SUCCESS
,
TDB_LOG_WARNING
,
"tdb_open: random from getpid and time"
);
return
ret
;
}
struct
new_database
{
struct
tdb_header
hdr
;
struct
tdb_freetable
ftable
;
};
/* initialise a new database */
static
enum
TDB_ERROR
tdb_new_database
(
struct
tdb_context
*
tdb
,
struct
tdb_attribute_seed
*
seed
,
struct
tdb_header
*
hdr
)
{
/* We make it up in memory, then write it out if not internal */
struct
new_database
newdb
;
unsigned
int
magic_len
;
ssize_t
rlen
;
enum
TDB_ERROR
ecode
;
/* Fill in the header */
newdb
.
hdr
.
version
=
TDB_VERSION
;
if
(
seed
)
newdb
.
hdr
.
hash_seed
=
seed
->
seed
;
else
newdb
.
hdr
.
hash_seed
=
random_number
(
tdb
);
newdb
.
hdr
.
hash_test
=
TDB_HASH_MAGIC
;
newdb
.
hdr
.
hash_test
=
tdb
->
khash
(
&
newdb
.
hdr
.
hash_test
,
sizeof
(
newdb
.
hdr
.
hash_test
),
newdb
.
hdr
.
hash_seed
,
tdb
->
hash_priv
);
newdb
.
hdr
.
recovery
=
0
;
newdb
.
hdr
.
features_used
=
newdb
.
hdr
.
features_offered
=
TDB_FEATURE_MASK
;
memset
(
newdb
.
hdr
.
reserved
,
0
,
sizeof
(
newdb
.
hdr
.
reserved
));
/* Initial hashes are empty. */
memset
(
newdb
.
hdr
.
hashtable
,
0
,
sizeof
(
newdb
.
hdr
.
hashtable
));
/* Free is empty. */
newdb
.
hdr
.
free_table
=
offsetof
(
struct
new_database
,
ftable
);
memset
(
&
newdb
.
ftable
,
0
,
sizeof
(
newdb
.
ftable
));
ecode
=
set_header
(
NULL
,
&
newdb
.
ftable
.
hdr
,
TDB_FTABLE_MAGIC
,
0
,
sizeof
(
newdb
.
ftable
)
-
sizeof
(
newdb
.
ftable
.
hdr
),
sizeof
(
newdb
.
ftable
)
-
sizeof
(
newdb
.
ftable
.
hdr
),
0
);
if
(
ecode
!=
TDB_SUCCESS
)
{
return
ecode
;
}
/* Magic food */
memset
(
newdb
.
hdr
.
magic_food
,
0
,
sizeof
(
newdb
.
hdr
.
magic_food
));
strcpy
(
newdb
.
hdr
.
magic_food
,
TDB_MAGIC_FOOD
);
/* This creates an endian-converted database, as if read from disk */
magic_len
=
sizeof
(
newdb
.
hdr
.
magic_food
);
tdb_convert
(
tdb
,
(
char
*
)
&
newdb
.
hdr
+
magic_len
,
sizeof
(
newdb
)
-
magic_len
);
*
hdr
=
newdb
.
hdr
;
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
tdb
->
map_size
=
sizeof
(
newdb
);
tdb
->
map_ptr
=
malloc
(
tdb
->
map_size
);
if
(
!
tdb
->
map_ptr
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to allocate"
);
}
memcpy
(
tdb
->
map_ptr
,
&
newdb
,
tdb
->
map_size
);
return
TDB_SUCCESS
;
}
if
(
lseek
(
tdb
->
fd
,
0
,
SEEK_SET
)
==
-
1
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to seek: %s"
,
strerror
(
errno
));
}
if
(
ftruncate
(
tdb
->
fd
,
0
)
==
-
1
)
{
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database:"
" failed to truncate: %s"
,
strerror
(
errno
));
}
rlen
=
write
(
tdb
->
fd
,
&
newdb
,
sizeof
(
newdb
));
if
(
rlen
!=
sizeof
(
newdb
))
{
if
(
rlen
>=
0
)
errno
=
ENOSPC
;
return
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_new_database: %zi writing header: %s"
,
rlen
,
strerror
(
errno
));
}
return
TDB_SUCCESS
;
}
struct
tdb_context
*
tdb_open
(
const
char
*
name
,
int
tdb_flags
,
int
open_flags
,
mode_t
mode
,
union
tdb_attribute
*
attr
)
{
struct
tdb_context
*
tdb
;
struct
stat
st
;
int
saved_errno
=
0
;
uint64_t
hash_test
;
unsigned
v
;
ssize_t
rlen
;
struct
tdb_header
hdr
;
struct
tdb_attribute_seed
*
seed
=
NULL
;
tdb_bool_err
berr
;
enum
TDB_ERROR
ecode
;
tdb
=
malloc
(
sizeof
(
*
tdb
));
if
(
!
tdb
)
{
/* Can't log this */
errno
=
ENOMEM
;
return
NULL
;
}
tdb
->
name
=
NULL
;
tdb
->
map_ptr
=
NULL
;
tdb
->
direct_access
=
0
;
tdb
->
fd
=
-
1
;
tdb
->
map_size
=
sizeof
(
struct
tdb_header
);
tdb
->
flags
=
tdb_flags
;
tdb
->
logfn
=
NULL
;
tdb
->
transaction
=
NULL
;
tdb
->
stats
=
NULL
;
tdb
->
access
=
NULL
;
tdb_hash_init
(
tdb
);
tdb_io_init
(
tdb
);
tdb_lock_init
(
tdb
);
while
(
attr
)
{
switch
(
attr
->
base
.
attr
)
{
case
TDB_ATTRIBUTE_LOG
:
tdb
->
logfn
=
attr
->
log
.
log_fn
;
tdb
->
log_private
=
attr
->
log
.
log_private
;
break
;
case
TDB_ATTRIBUTE_HASH
:
tdb
->
khash
=
attr
->
hash
.
hash_fn
;
tdb
->
hash_priv
=
attr
->
hash
.
hash_private
;
break
;
case
TDB_ATTRIBUTE_SEED
:
seed
=
&
attr
->
seed
;
break
;
case
TDB_ATTRIBUTE_STATS
:
tdb
->
stats
=
&
attr
->
stats
;
/* They have stats we don't know about? Tell them. */
if
(
tdb
->
stats
->
size
>
sizeof
(
attr
->
stats
))
tdb
->
stats
->
size
=
sizeof
(
attr
->
stats
);
break
;
default:
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open:"
" unknown attribute type %u"
,
attr
->
base
.
attr
);
goto
fail
;
}
attr
=
attr
->
base
.
next
;
}
if
(
tdb_flags
&
~
(
TDB_INTERNAL
|
TDB_NOLOCK
|
TDB_NOMMAP
|
TDB_CONVERT
|
TDB_NOSYNC
))
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open: unknown flags %u"
,
tdb_flags
);
goto
fail
;
}
if
((
open_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_EINVAL
,
TDB_LOG_USE_ERROR
,
"tdb_open: can't open tdb %s write-only"
,
name
);
goto
fail
;
}
if
((
open_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
tdb
->
read_only
=
true
;
tdb
->
mmap_flags
=
PROT_READ
;
}
else
{
tdb
->
read_only
=
false
;
tdb
->
mmap_flags
=
PROT_READ
|
PROT_WRITE
;
}
/* internal databases don't need any of the rest. */
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
tdb
->
flags
|=
(
TDB_NOLOCK
|
TDB_NOMMAP
);
ecode
=
tdb_new_database
(
tdb
,
seed
,
&
hdr
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
tdb_convert
(
tdb
,
&
hdr
.
hash_seed
,
sizeof
(
hdr
.
hash_seed
));
tdb
->
hash_seed
=
hdr
.
hash_seed
;
tdb_ftable_init
(
tdb
);
return
tdb
;
}
if
((
tdb
->
fd
=
open
(
name
,
open_flags
,
mode
))
==
-
1
)
{
/* errno set by open(2) */
saved_errno
=
errno
;
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: could not open file %s: %s"
,
name
,
strerror
(
errno
));
goto
fail
;
}
/* on exec, don't inherit the fd */
v
=
fcntl
(
tdb
->
fd
,
F_GETFD
,
0
);
fcntl
(
tdb
->
fd
,
F_SETFD
,
v
|
FD_CLOEXEC
);
/* ensure there is only one process initialising at once */
ecode
=
tdb_lock_open
(
tdb
,
TDB_LOCK_WAIT
|
TDB_LOCK_NOCHECK
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
/* If they used O_TRUNC, read will return 0. */
rlen
=
read
(
tdb
->
fd
,
&
hdr
,
sizeof
(
hdr
));
if
(
rlen
==
0
&&
(
open_flags
&
O_CREAT
))
{
ecode
=
tdb_new_database
(
tdb
,
seed
,
&
hdr
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
}
else
if
(
rlen
<
0
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: error %s reading %s"
,
strerror
(
errno
),
name
);
goto
fail
;
}
else
if
(
rlen
<
sizeof
(
hdr
)
||
strcmp
(
hdr
.
magic_food
,
TDB_MAGIC_FOOD
)
!=
0
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: %s is not a tdb file"
,
name
);
goto
fail
;
}
if
(
hdr
.
version
!=
TDB_VERSION
)
{
if
(
hdr
.
version
==
bswap_64
(
TDB_VERSION
))
tdb
->
flags
|=
TDB_CONVERT
;
else
{
/* wrong version */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open:"
" %s is unknown version 0x%llx"
,
name
,
(
long
long
)
hdr
.
version
);
goto
fail
;
}
}
tdb_convert
(
tdb
,
&
hdr
,
sizeof
(
hdr
));
tdb
->
hash_seed
=
hdr
.
hash_seed
;
hash_test
=
TDB_HASH_MAGIC
;
hash_test
=
tdb_hash
(
tdb
,
&
hash_test
,
sizeof
(
hash_test
));
if
(
hdr
.
hash_test
!=
hash_test
)
{
/* wrong hash variant */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open:"
" %s uses a different hash function"
,
name
);
goto
fail
;
}
if
(
fstat
(
tdb
->
fd
,
&
st
)
==
-
1
)
{
saved_errno
=
errno
;
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: could not stat open %s: %s"
,
name
,
strerror
(
errno
));
goto
fail
;
}
/* Is it already in the open list? If so, fail. */
if
(
tdb_already_open
(
st
.
st_dev
,
st
.
st_ino
))
{
/* FIXME */
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_USE_ERROR
,
"tdb_open: %s (%d,%d) is already open"
" in this process"
,
name
,
(
int
)
st
.
st_dev
,
(
int
)
st
.
st_ino
);
goto
fail
;
}
tdb
->
name
=
strdup
(
name
);
if
(
!
tdb
->
name
)
{
ecode
=
tdb_logerr
(
tdb
,
TDB_ERR_OOM
,
TDB_LOG_ERROR
,
"tdb_open: failed to allocate name"
);
goto
fail
;
}
/* Clear any features we don't understand. */
if
((
open_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
hdr
.
features_used
&=
TDB_FEATURE_MASK
;
if
(
tdb_write_convert
(
tdb
,
offsetof
(
struct
tdb_header
,
features_used
),
&
hdr
.
features_used
,
sizeof
(
hdr
.
features_used
))
==
-
1
)
goto
fail
;
}
tdb
->
device
=
st
.
st_dev
;
tdb
->
inode
=
st
.
st_ino
;
tdb_unlock_open
(
tdb
);
/* This make sure we have current map_size and mmap. */
tdb
->
methods
->
oob
(
tdb
,
tdb
->
map_size
+
1
,
true
);
/* Now it's fully formed, recover if necessary. */
berr
=
tdb_needs_recovery
(
tdb
);
if
(
unlikely
(
berr
!=
false
))
{
if
(
berr
<
0
)
{
ecode
=
berr
;
goto
fail
;
}
ecode
=
tdb_lock_and_recover
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
}
ecode
=
tdb_ftable_init
(
tdb
);
if
(
ecode
!=
TDB_SUCCESS
)
{
goto
fail
;
}
tdb
->
next
=
tdbs
;
tdbs
=
tdb
;
return
tdb
;
fail:
/* Map ecode to some logical errno. */
if
(
!
saved_errno
)
{
switch
(
ecode
)
{
case
TDB_ERR_CORRUPT
:
case
TDB_ERR_IO
:
saved_errno
=
EIO
;
break
;
case
TDB_ERR_LOCK
:
saved_errno
=
EWOULDBLOCK
;
break
;
case
TDB_ERR_OOM
:
saved_errno
=
ENOMEM
;
break
;
case
TDB_ERR_EINVAL
:
saved_errno
=
EINVAL
;
break
;
default:
saved_errno
=
EINVAL
;
break
;
}
}
#ifdef TDB_TRACE
close
(
tdb
->
tracefd
);
#endif
if
(
tdb
->
map_ptr
)
{
if
(
tdb
->
flags
&
TDB_INTERNAL
)
{
free
(
tdb
->
map_ptr
);
}
else
tdb_munmap
(
tdb
);
}
free
(
tdb
->
lockrecs
);
free
((
char
*
)
tdb
->
name
);
if
(
tdb
->
fd
!=
-
1
)
if
(
close
(
tdb
->
fd
)
!=
0
)
tdb_logerr
(
tdb
,
TDB_ERR_IO
,
TDB_LOG_ERROR
,
"tdb_open: failed to close tdb->fd"
" on error: %s"
,
strerror
(
errno
));
free
(
tdb
);
errno
=
saved_errno
;
return
NULL
;
}
static
enum
TDB_ERROR
update_rec_hdr
(
struct
tdb_context
*
tdb
,
static
enum
TDB_ERROR
update_rec_hdr
(
struct
tdb_context
*
tdb
,
tdb_off_t
off
,
tdb_off_t
off
,
tdb_len_t
keylen
,
tdb_len_t
keylen
,
...
@@ -718,46 +278,6 @@ unlock:
...
@@ -718,46 +278,6 @@ unlock:
return
ecode
;
return
ecode
;
}
}
int
tdb_close
(
struct
tdb_context
*
tdb
)
{
struct
tdb_context
**
i
;
int
ret
=
0
;
tdb_trace
(
tdb
,
"tdb_close"
);
if
(
tdb
->
transaction
)
{
tdb_transaction_cancel
(
tdb
);
}
if
(
tdb
->
map_ptr
)
{
if
(
tdb
->
flags
&
TDB_INTERNAL
)
free
(
tdb
->
map_ptr
);
else
tdb_munmap
(
tdb
);
}
free
((
char
*
)
tdb
->
name
);
if
(
tdb
->
fd
!=
-
1
)
{
ret
=
close
(
tdb
->
fd
);
tdb
->
fd
=
-
1
;
}
free
(
tdb
->
lockrecs
);
/* Remove from contexts list */
for
(
i
=
&
tdbs
;
*
i
;
i
=
&
(
*
i
)
->
next
)
{
if
(
*
i
==
tdb
)
{
*
i
=
tdb
->
next
;
break
;
}
}
#ifdef TDB_TRACE
close
(
tdb
->
tracefd
);
#endif
free
(
tdb
);
return
ret
;
}
unsigned
int
tdb_get_flags
(
struct
tdb_context
*
tdb
)
unsigned
int
tdb_get_flags
(
struct
tdb_context
*
tdb
)
{
{
return
tdb
->
flags
;
return
tdb
->
flags
;
...
...
ccan/tdb2/test/failtest_helper.h
View file @
efdf0f2d
...
@@ -4,9 +4,9 @@
...
@@ -4,9 +4,9 @@
#include <stdbool.h>
#include <stdbool.h>
/* FIXME: Check these! */
/* FIXME: Check these! */
#define INITIAL_TDB_MALLOC "
tdb.c", 191
, FAILTEST_MALLOC
#define INITIAL_TDB_MALLOC "
open.c", 184
, FAILTEST_MALLOC
#define URANDOM_OPEN "
tdb.c", 49
, FAILTEST_OPEN
#define URANDOM_OPEN "
open.c", 43
, FAILTEST_OPEN
#define URANDOM_READ "
tdb.c", 29
, FAILTEST_READ
#define URANDOM_READ "
open.c", 23
, FAILTEST_READ
bool
exit_check_log
(
struct
failtest_call
*
history
,
unsigned
num
);
bool
exit_check_log
(
struct
failtest_call
*
history
,
unsigned
num
);
bool
failmatch
(
const
struct
failtest_call
*
call
,
bool
failmatch
(
const
struct
failtest_call
*
call
,
...
...
ccan/tdb2/test/run-001-encode.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/hash.c>
#include <ccan/tdb2/hash.c>
...
...
ccan/tdb2/test/run-001-fls.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-01-new_database.c
View file @
efdf0f2d
#include <ccan/failtest/failtest_override.h>
#include <ccan/failtest/failtest_override.h>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-02-expand.c
View file @
efdf0f2d
#include <ccan/failtest/failtest_override.h>
#include <ccan/failtest/failtest_override.h>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-03-coalesce.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-04-basichash.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-10-simple-store.c
View file @
efdf0f2d
#include <ccan/failtest/failtest_override.h>
#include <ccan/failtest/failtest_override.h>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-11-simple-fetch.c
View file @
efdf0f2d
#include <ccan/failtest/failtest_override.h>
#include <ccan/failtest/failtest_override.h>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-12-store.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-13-delete.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-15-append.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-20-growhash.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-25-hashoverload.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-30-exhaust-before-expand.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-50-multiple-freelists.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-55-transaction.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-56-open-during-transaction.c
View file @
efdf0f2d
...
@@ -12,6 +12,7 @@ static int ftruncate_check(int fd, off_t length);
...
@@ -12,6 +12,7 @@ static int ftruncate_check(int fd, off_t length);
#define ftruncate ftruncate_check
#define ftruncate ftruncate_check
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-57-die-during-transaction.c
View file @
efdf0f2d
...
@@ -59,6 +59,7 @@ static void free_all(void)
...
@@ -59,6 +59,7 @@ static void free_all(void)
#define free free_noleak
#define free free_noleak
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-add-remove-flags.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-features.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-firstkey-nextkey.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-missing-entries.c
View file @
efdf0f2d
/* Another test revealed that we lost an entry. This reproduces it. */
/* Another test revealed that we lost an entry. This reproduces it. */
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-record-expand.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-remap-in-read_traverse.c
View file @
efdf0f2d
/* We had a bug where we marked the tdb read-only for a tdb_traverse_read.
/* We had a bug where we marked the tdb read-only for a tdb_traverse_read.
* If we then expanded the tdb, we would remap read-only, and later SEGV. */
* If we then expanded the tdb, we would remap read-only, and later SEGV. */
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-seed.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-simple-delete.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-summary.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-tdb_errorstr.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
ccan/tdb2/test/run-traverse.c
View file @
efdf0f2d
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/tdb.c>
#include <ccan/tdb2/open.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/lock.c>
#include <ccan/tdb2/io.c>
#include <ccan/tdb2/io.c>
...
...
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