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
42145b92
Commit
42145b92
authored
Jul 15, 2009
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Print seq numbers on timeout dump
(Invasive: means passing full op array all the way through).
parent
010c8d46
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
85 additions
and
68 deletions
+85
-68
ccan/tdb/tools/replay_trace.c
ccan/tdb/tools/replay_trace.c
+85
-68
No files found.
ccan/tdb/tools/replay_trace.c
View file @
42145b92
...
...
@@ -22,7 +22,7 @@
/* Avoid mod by zero */
static
unsigned
int
total_keys
=
1
;
/* #define DEBUG_DEPS 1 */
#define DEBUG_DEPS 1
/* Traversals block transactions in the current implementation. */
#define TRAVERSALS_TAKE_TRANSACTION_LOCK 1
...
...
@@ -404,23 +404,26 @@ static void check_deps(const char *filename, struct op op[], unsigned int num)
#endif
}
static
void
dump_pre
(
char
*
filename
[],
unsigned
int
file
,
struct
op
op
[]
,
unsigned
int
i
)
static
void
dump_pre
(
char
*
filename
[],
struct
op
*
op
[]
,
unsigned
int
file
,
unsigned
int
i
)
{
struct
depend
*
dep
;
printf
(
"%s:%u still waiting for:
\n
"
,
filename
[
file
],
i
+
1
);
list_for_each
(
&
op
[
i
].
pre
,
dep
,
pre_list
)
printf
(
" %s:%u
\n
"
,
filename
[
dep
->
satisfies_file
],
dep
->
satisfies_opnum
+
1
);
check_deps
(
filename
[
file
],
op
,
i
);
printf
(
"%s:%u (%u) still waiting for:
\n
"
,
filename
[
file
],
i
+
1
,
op
[
file
][
i
].
serial
);
list_for_each
(
&
op
[
file
][
i
].
pre
,
dep
,
pre_list
)
printf
(
" %s:%u (%u)
\n
"
,
filename
[
dep
->
satisfies_file
],
dep
->
satisfies_opnum
+
1
,
op
[
dep
->
satisfies_file
][
dep
->
satisfies_opnum
].
serial
);
check_deps
(
filename
[
file
],
op
[
file
],
i
);
}
/* We simply read/write pointers, since we all are children. */
static
void
do_pre
(
char
*
filename
[],
unsigned
int
file
,
int
pre_fd
,
struct
op
op
[],
unsigned
int
i
)
static
void
do_pre
(
struct
tdb_context
*
tdb
,
char
*
filename
[],
struct
op
*
op
[],
unsigned
int
file
,
int
pre_fd
,
unsigned
int
i
)
{
while
(
!
list_empty
(
&
op
[
i
].
pre
))
{
while
(
!
list_empty
(
&
op
[
file
][
i
].
pre
))
{
struct
depend
*
dep
;
#if DEBUG_DEPS
...
...
@@ -430,7 +433,7 @@ static void do_pre(char *filename[], unsigned int file, int pre_fd,
alarm
(
10
);
while
(
read
(
pre_fd
,
&
dep
,
sizeof
(
dep
))
!=
sizeof
(
dep
))
{
if
(
errno
==
EINTR
)
{
dump_pre
(
filename
,
file
,
op
,
i
);
dump_pre
(
filename
,
op
,
file
,
i
);
exit
(
1
);
}
else
errx
(
1
,
"Reading from pipe"
);
...
...
@@ -448,12 +451,12 @@ static void do_pre(char *filename[], unsigned int file, int pre_fd,
}
}
static
void
do_post
(
char
*
filename
[],
unsigned
int
file
,
const
struct
op
op
[]
,
unsigned
int
i
)
static
void
do_post
(
char
*
filename
[],
struct
op
*
op
[]
,
unsigned
int
file
,
unsigned
int
i
)
{
struct
depend
*
dep
;
list_for_each
(
&
op
[
i
].
post
,
dep
,
post_list
)
{
list_for_each
(
&
op
[
file
][
i
].
post
,
dep
,
post_list
)
{
#if DEBUG_DEPS
printf
(
"%s:%u:sending to file %s:%u
\n
"
,
filename
[
file
],
i
+
1
,
filename
[
dep
->
needs_file
],
dep
->
needs_opnum
+
1
);
...
...
@@ -473,12 +476,12 @@ static int get_len(TDB_DATA key, TDB_DATA data, void *private_data)
static
unsigned
run_ops
(
struct
tdb_context
*
tdb
,
int
pre_fd
,
char
*
filename
[],
struct
op
*
op
[],
unsigned
int
file
,
struct
op
op
[],
unsigned
int
start
,
unsigned
int
stop
);
struct
traverse_info
{
struct
op
*
op
;
struct
op
*
*
op
;
char
**
filename
;
unsigned
file
;
int
pre_fd
;
...
...
@@ -492,7 +495,7 @@ static int nontrivial_traverse(struct tdb_context *tdb,
void
*
_tinfo
)
{
struct
traverse_info
*
tinfo
=
_tinfo
;
unsigned
int
trav_len
=
tinfo
->
op
[
tinfo
->
start
].
group_len
;
unsigned
int
trav_len
=
tinfo
->
op
[
tinfo
->
file
][
tinfo
->
start
].
group_len
;
if
(
tinfo
->
i
==
tinfo
->
start
+
trav_len
)
{
/* This can happen if traverse expects to be empty. */
...
...
@@ -502,13 +505,13 @@ static int nontrivial_traverse(struct tdb_context *tdb,
"traverse did not terminate"
);
}
if
(
tinfo
->
op
[
tinfo
->
i
].
op
!=
OP_TDB_TRAVERSE
)
if
(
tinfo
->
op
[
tinfo
->
file
][
tinfo
->
i
].
op
!=
OP_TDB_TRAVERSE
)
fail
(
tinfo
->
filename
[
tinfo
->
file
],
tinfo
->
start
+
1
,
"%s:%u:traverse terminated early"
);
/* Run any normal ops. */
tinfo
->
i
=
run_ops
(
tdb
,
tinfo
->
pre_fd
,
tinfo
->
filename
,
tinfo
->
file
,
tinfo
->
op
,
tinfo
->
i
+
1
,
tinfo
->
start
+
trav_len
);
tinfo
->
i
=
run_ops
(
tdb
,
tinfo
->
pre_fd
,
tinfo
->
filename
,
tinfo
->
op
,
tinfo
->
file
,
tinfo
->
i
+
1
,
tinfo
->
start
+
trav_len
);
if
(
tinfo
->
i
==
tinfo
->
start
+
trav_len
)
return
1
;
...
...
@@ -522,7 +525,7 @@ static unsigned op_traverse(struct tdb_context *tdb,
unsigned
int
file
,
int
(
*
traversefn
)(
struct
tdb_context
*
,
tdb_traverse_func
,
void
*
),
struct
op
op
[],
struct
op
*
op
[],
unsigned
int
start
)
{
struct
traverse_info
tinfo
=
{
op
,
filename
,
file
,
pre_fd
,
...
...
@@ -533,12 +536,13 @@ static unsigned op_traverse(struct tdb_context *tdb,
/* Traversing in wrong order can have strange effects: eg. if
* original traverse went A (delete A), B, we might do B
* (delete A). So if we have ops left over, we do it now. */
while
(
tinfo
.
i
!=
start
+
op
[
start
].
group_len
)
{
if
(
op
[
tinfo
.
i
].
op
==
OP_TDB_TRAVERSE
)
while
(
tinfo
.
i
!=
start
+
op
[
file
][
start
].
group_len
)
{
if
(
op
[
file
][
tinfo
.
i
].
op
==
OP_TDB_TRAVERSE
)
tinfo
.
i
++
;
else
tinfo
.
i
=
run_ops
(
tdb
,
pre_fd
,
filename
,
file
,
op
,
tinfo
.
i
,
start
+
op
[
start
].
group_len
);
tinfo
.
i
=
run_ops
(
tdb
,
pre_fd
,
filename
,
op
,
file
,
tinfo
.
i
,
start
+
op
[
file
][
start
].
group_len
);
}
return
tinfo
.
i
;
...
...
@@ -552,8 +556,9 @@ static __attribute__((noinline))
unsigned
run_ops
(
struct
tdb_context
*
tdb
,
int
pre_fd
,
char
*
filename
[],
struct
op
*
op
[],
unsigned
int
file
,
struct
op
op
[],
unsigned
int
start
,
unsigned
int
stop
)
unsigned
int
start
,
unsigned
int
stop
)
{
unsigned
int
i
;
struct
sigaction
sa
;
...
...
@@ -563,88 +568,98 @@ unsigned run_ops(struct tdb_context *tdb,
sigaction
(
SIGALRM
,
&
sa
,
NULL
);
for
(
i
=
start
;
i
<
stop
;
i
++
)
{
do_pre
(
filename
,
file
,
pre_fd
,
op
,
i
);
do_pre
(
tdb
,
filename
,
op
,
file
,
pre_fd
,
i
);
switch
(
op
[
i
].
op
)
{
switch
(
op
[
file
][
i
].
op
)
{
case
OP_TDB_LOCKALL
:
try
(
tdb_lockall
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_lockall
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_LOCKALL_MARK
:
try
(
tdb_lockall_mark
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_lockall_mark
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_LOCKALL_UNMARK
:
try
(
tdb_lockall_unmark
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_lockall_unmark
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_LOCKALL_NONBLOCK
:
unreliable
(
tdb_lockall_nonblock
(
tdb
),
op
[
i
].
ret
,
unreliable
(
tdb_lockall_nonblock
(
tdb
),
op
[
file
][
i
].
ret
,
tdb_lockall
(
tdb
),
tdb_unlockall
(
tdb
));
break
;
case
OP_TDB_UNLOCKALL
:
try
(
tdb_unlockall
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_unlockall
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_LOCKALL_READ
:
try
(
tdb_lockall_read
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_lockall_read
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_LOCKALL_READ_NONBLOCK
:
unreliable
(
tdb_lockall_read_nonblock
(
tdb
),
op
[
i
].
ret
,
unreliable
(
tdb_lockall_read_nonblock
(
tdb
),
op
[
file
][
i
].
ret
,
tdb_lockall_read
(
tdb
),
tdb_unlockall_read
(
tdb
));
break
;
case
OP_TDB_UNLOCKALL_READ
:
try
(
tdb_unlockall_read
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_unlockall_read
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINLOCK
:
try
(
tdb_chainlock
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainlock
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINLOCK_NONBLOCK
:
unreliable
(
tdb_chainlock_nonblock
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
,
tdb_chainlock
(
tdb
,
op
[
i
].
key
),
tdb_chainunlock
(
tdb
,
op
[
i
].
key
));
unreliable
(
tdb_chainlock_nonblock
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
,
tdb_chainlock
(
tdb
,
op
[
file
][
i
].
key
),
tdb_chainunlock
(
tdb
,
op
[
file
][
i
].
key
));
break
;
case
OP_TDB_CHAINLOCK_MARK
:
try
(
tdb_chainlock_mark
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainlock_mark
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINLOCK_UNMARK
:
try
(
tdb_chainlock_unmark
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainlock_unmark
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINUNLOCK
:
try
(
tdb_chainunlock
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainunlock
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINLOCK_READ
:
try
(
tdb_chainlock_read
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainlock_read
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_CHAINUNLOCK_READ
:
try
(
tdb_chainunlock_read
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_chainunlock_read
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_PARSE_RECORD
:
try
(
tdb_parse_record
(
tdb
,
op
[
i
].
key
,
get_len
,
NULL
),
op
[
i
].
ret
);
try
(
tdb_parse_record
(
tdb
,
op
[
file
][
i
].
key
,
get_len
,
NULL
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_EXISTS
:
try
(
tdb_exists
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_exists
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
]
[
i
].
ret
);
break
;
case
OP_TDB_STORE
:
try
(
tdb_store
(
tdb
,
op
[
i
].
key
,
op
[
i
].
data
,
op
[
i
].
flag
),
op
[
i
].
ret
);
try
(
tdb_store
(
tdb
,
op
[
file
][
i
].
key
,
op
[
file
][
i
].
data
,
op
[
file
][
i
].
flag
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_APPEND
:
try
(
tdb_append
(
tdb
,
op
[
i
].
key
,
op
[
i
].
data
),
op
[
i
].
ret
);
try
(
tdb_append
(
tdb
,
op
[
file
][
i
].
key
,
op
[
file
][
i
].
data
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_GET_SEQNUM
:
try
(
tdb_get_seqnum
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_get_seqnum
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_WIPE_ALL
:
try
(
tdb_wipe_all
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_wipe_all
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_TRANSACTION_START
:
try
(
tdb_transaction_start
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_transaction_start
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_TRANSACTION_CANCEL
:
try
(
tdb_transaction_cancel
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_transaction_cancel
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_TRANSACTION_COMMIT
:
try
(
tdb_transaction_commit
(
tdb
),
op
[
i
].
ret
);
try
(
tdb_transaction_commit
(
tdb
),
op
[
file
][
i
].
ret
);
break
;
case
OP_TDB_TRAVERSE_READ_START
:
i
=
op_traverse
(
tdb
,
pre_fd
,
filename
,
file
,
...
...
@@ -662,25 +677,26 @@ unsigned run_ops(struct tdb_context *tdb,
fail
(
filename
[
file
],
i
+
1
,
"unexpected end traverse"
);
/* FIXME: These must be treated like traverse. */
case
OP_TDB_FIRSTKEY
:
if
(
!
key_eq
(
tdb_firstkey
(
tdb
),
op
[
i
].
data
))
if
(
!
key_eq
(
tdb_firstkey
(
tdb
),
op
[
file
][
i
].
data
))
fail
(
filename
[
file
],
i
+
1
,
"bad firstkey"
);
break
;
case
OP_TDB_NEXTKEY
:
if
(
!
key_eq
(
tdb_nextkey
(
tdb
,
op
[
i
].
key
),
op
[
i
].
data
))
if
(
!
key_eq
(
tdb_nextkey
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
][
i
].
data
))
fail
(
filename
[
file
],
i
+
1
,
"bad nextkey"
);
break
;
case
OP_TDB_FETCH
:
{
TDB_DATA
f
=
tdb_fetch
(
tdb
,
op
[
i
].
key
);
if
(
!
key_eq
(
f
,
op
[
i
].
data
))
TDB_DATA
f
=
tdb_fetch
(
tdb
,
op
[
file
][
i
].
key
);
if
(
!
key_eq
(
f
,
op
[
file
][
i
].
data
))
fail
(
filename
[
file
],
i
+
1
,
"bad fetch %u"
,
f
.
dsize
);
break
;
}
case
OP_TDB_DELETE
:
try
(
tdb_delete
(
tdb
,
op
[
i
].
key
),
op
[
i
].
ret
);
try
(
tdb_delete
(
tdb
,
op
[
file
][
i
].
key
),
op
[
file
]
[
i
].
ret
);
break
;
}
do_post
(
filename
,
file
,
op
,
i
);
do_post
(
filename
,
op
,
file
,
i
);
}
return
i
;
}
...
...
@@ -1132,7 +1148,8 @@ struct traverse_dep {
unsigned
int
op_num
;
};
/* Traversals can deadlock against each other. Force order. */
/* Traversals can deadlock against each other, and transactions. Force
* order. */
static
void
make_traverse_depends
(
char
*
filename
[],
struct
op
*
op
[],
unsigned
int
num_ops
[],
unsigned
int
num
)
...
...
@@ -1160,7 +1177,7 @@ static void make_traverse_depends(char *filename[],
/* Count them. */
for
(
i
=
0
;
i
<
num
;
i
++
)
{
for
(
j
=
1
;
j
<
num_ops
[
i
];
j
++
)
{
/* Transaction on
traverse start. */
/* Transaction or
traverse start. */
if
(
op
[
i
][
j
].
group_start
==
j
)
{
dep
=
talloc_realloc
(
NULL
,
dep
,
struct
traverse_dep
,
...
...
@@ -1358,7 +1375,7 @@ int main(int argc, char *argv[])
printf
(
"Single threaded run..."
);
fflush
(
stdout
);
run_ops
(
tdb
,
pipes
[
0
].
fd
[
0
],
argv
+
2
,
0
,
op
[
0
]
,
1
,
num_ops
[
0
]);
run_ops
(
tdb
,
pipes
[
0
].
fd
[
0
],
argv
+
2
,
op
,
0
,
1
,
num_ops
[
0
]);
check_deps
(
argv
[
2
],
op
[
0
],
num_ops
[
0
]);
printf
(
"done
\n
"
);
...
...
@@ -1385,7 +1402,7 @@ int main(int argc, char *argv[])
/* This catches parent exiting. */
if
(
read
(
fds
[
0
],
&
c
,
1
)
!=
1
)
exit
(
1
);
run_ops
(
tdb
,
pipes
[
i
].
fd
[
0
],
argv
+
2
,
i
,
op
[
i
]
,
1
,
run_ops
(
tdb
,
pipes
[
i
].
fd
[
0
],
argv
+
2
,
op
,
i
,
1
,
num_ops
[
i
]);
check_deps
(
argv
[
2
+
i
],
op
[
i
],
num_ops
[
i
]);
exit
(
0
);
...
...
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