3 #include "lock-tracking.h"
5 static ssize_t
pwrite_check(int fd
, const void *buf
, size_t count
, off_t offset
);
6 static ssize_t
write_check(int fd
, const void *buf
, size_t count
);
7 static int ftruncate_check(int fd
, off_t length
);
9 #define pwrite pwrite_check
10 #define write write_check
11 #define fcntl fcntl_with_lockcheck
12 #define ftruncate ftruncate_check
14 #include "ntdb-source.h"
15 #include "tap-interface.h"
19 #include "external-agent.h"
22 static struct agent
*agent
;
24 static int errors
= 0;
25 #define TEST_DBNAME "run-56-open-during-transaction.ntdb"
32 static bool is_same(const char *snapshot
, const char *latest
, off_t len
)
36 for (i
= 0; i
< len
; i
++) {
37 if (snapshot
[i
] != latest
[i
])
43 static bool compare_file(int fd
, const char *snapshot
, off_t snapshot_len
)
48 /* over-length read serves as length check. */
49 contents
= malloc(snapshot_len
+1);
50 ret
= pread(fd
, contents
, snapshot_len
+1, 0) == snapshot_len
51 && is_same(snapshot
, contents
, snapshot_len
);
56 static void check_file_intact(int fd
)
58 enum agent_return ret
;
63 contents
= malloc(st
.st_size
);
64 if (pread(fd
, contents
, st
.st_size
, 0) != st
.st_size
) {
70 /* Ask agent to open file. */
71 ret
= external_agent_operation(agent
, OPEN
, TEST_DBNAME
);
73 /* It's OK to open it, but it must not have changed! */
74 if (!compare_file(fd
, contents
, st
.st_size
)) {
75 diag("Agent changed file after opening %s",
76 agent_return_name(ret
));
81 ret
= external_agent_operation(agent
, CLOSE
, NULL
);
83 diag("Agent failed to close ntdb: %s",
84 agent_return_name(ret
));
87 } else if (ret
!= WOULD_HAVE_BLOCKED
) {
88 diag("Agent opening file gave %s",
89 agent_return_name(ret
));
96 static void after_unlock(int fd
)
99 check_file_intact(fd
);
102 static ssize_t
pwrite_check(int fd
,
103 const void *buf
, size_t count
, off_t offset
)
106 check_file_intact(fd
);
108 return pwrite(fd
, buf
, count
, offset
);
111 static ssize_t
write_check(int fd
, const void *buf
, size_t count
)
114 check_file_intact(fd
);
116 return write(fd
, buf
, count
);
119 static int ftruncate_check(int fd
, off_t length
)
122 check_file_intact(fd
);
124 return ftruncate(fd
, length
);
128 int main(int argc
, char *argv
[])
130 const int flags
[] = { NTDB_DEFAULT
, NTDB_NOMMAP
,
131 NTDB_CONVERT
, NTDB_NOMMAP
|NTDB_CONVERT
};
133 struct ntdb_context
*ntdb
;
136 plan_tests(sizeof(flags
)/sizeof(flags
[0]) * 5);
137 agent
= prepare_external_agent();
139 err(1, "preparing agent");
141 unlock_callback
= after_unlock
;
142 for (i
= 0; i
< sizeof(flags
)/sizeof(flags
[0]); i
++) {
143 diag("Test with %s and %s\n",
144 (flags
[i
] & NTDB_CONVERT
) ? "CONVERT" : "DEFAULT",
145 (flags
[i
] & NTDB_NOMMAP
) ? "no mmap" : "mmap");
147 ntdb
= ntdb_open(TEST_DBNAME
, flags
[i
]|MAYBE_NOSYNC
,
148 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &tap_log_attr
);
152 ok1(ntdb_transaction_start(ntdb
) == 0);
153 key
= ntdb_mkdata("hi", strlen("hi"));
154 data
= ntdb_mkdata("world", strlen("world"));
156 ok1(ntdb_store(ntdb
, key
, data
, NTDB_INSERT
) == 0);
157 ok1(ntdb_transaction_commit(ntdb
) == 0);
158 ok(!errors
, "We had %u open errors", errors
);
164 return exit_status();