Skip to content

Commit 23f70d7

Browse files
committed
Add bulk import tests
Signed-off-by: mdouglas47 <[email protected]>
1 parent ba57646 commit 23f70d7

File tree

7 files changed

+178
-23
lines changed

7 files changed

+178
-23
lines changed

db/db_tunables.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ extern int gbl_recovery_ckp;
151151
extern int gbl_reproduce_ckp_bug;
152152
extern int gbl_sample_queries;
153153
extern int gbl_sample_queries_max_queries;
154+
extern int gbl_comdb2_files_sleep_secs_after_processing_llmeta;
154155
extern int gbl_slow_rep_process_txn_freq;
155156
extern int gbl_slow_rep_process_txn_minms;
156157
extern int gbl_slow_rep_process_txn_maxms;

db/db_tunables.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,6 +2556,9 @@ REGISTER_TUNABLE("iam_dbname",
25562556
"override dbname for IAM",
25572557
TUNABLE_STRING, &gbl_iam_dbname, READEARLY | READONLY, NULL,
25582558
NULL, NULL, NULL);
2559+
REGISTER_TUNABLE("comdb2_files_sleep_secs_after_processing_llmeta", "Number of seconds to sleep after processing "
2560+
"llmeta in comdb2 files query processor\n", TUNABLE_INTEGER,
2561+
&gbl_comdb2_files_sleep_secs_after_processing_llmeta, INTERNAL, NULL, NULL, NULL, NULL);
25592562
REGISTER_TUNABLE("comdb2_oplog_preserve_seqno", "Preserve max value of the seqno in llmeta", TUNABLE_BOOLEAN, &gbl_comdb2_oplog_preserve_seqno, INTERNAL, NULL, NULL, NULL, NULL);
25602563
REGISTER_TUNABLE("queue_nonodh_scan_limit", "For comdb2_queues, stop queue scan at this depth (Default: 10000)", TUNABLE_INTEGER, &gbl_nonodh_queue_scan_limit, 0, NULL, NULL, NULL, NULL);
25612564
REGISTER_TUNABLE("always_request_log_req", "Always request the next log record on replicant if there is a gap (default: off)", TUNABLE_BOOLEAN, &gbl_always_request_log_req, 0, NULL, NULL, NULL, NULL);

sqlite/ext/comdb2/files.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
typedef unsigned char u_int8_t;
2424

25+
int gbl_comdb2_files_sleep_secs_after_processing_llmeta = 0;
2526
int endianness_mismatch(struct sqlclntstate *clnt);
2627
void berk_fix_checkpoint_endianness(u_int8_t *buffer);
2728

@@ -131,19 +132,19 @@ static int check_and_append_new_log_files(systbl_files_cursor *pCur)
131132
static int read_next_chunk(systbl_files_cursor *pCur)
132133
{
133134
while (pCur->rowid < pCur->nfiles) {
134-
logmsg(LOGMSG_DEBUG, "%s:%d processing %s\n", __func__, __LINE__,
135-
pCur->files[pCur->rowid].name);
135+
const char * const fname = pCur->files[pCur->rowid].name;
136+
logmsg(LOGMSG_DEBUG, "%s:%d processing %s\n", __func__, __LINE__, fname);
136137

137138
if (pCur->files[pCur->rowid].type == FILES_TYPE_LOGFILE) {
138139
if (check_and_append_new_log_files(pCur) != 0) {
139-
logmsg(LOGMSG_ERROR, "%s:%d Failed to process file %s\n", __func__, __LINE__, pCur->files[pCur->rowid].name);
140+
logmsg(LOGMSG_ERROR, "%s:%d Failed to process file %s\n", __func__, __LINE__, fname);
140141
return SQLITE_ERROR;
141142
}
142143
}
143144

144145
int rc = read_write_file(pCur->files[pCur->rowid].info, pCur, memory_writer);
145146
if (rc > 0) {
146-
logmsg(LOGMSG_ERROR, "%s:%d Failed to process file %s\n", __func__, __LINE__, pCur->files[pCur->rowid].name);
147+
logmsg(LOGMSG_ERROR, "%s:%d Failed to process file %s\n", __func__, __LINE__, fname);
147148
return SQLITE_ERROR;
148149
} else if (rc == 0) {
149150
break;
@@ -160,6 +161,14 @@ static int read_next_chunk(systbl_files_cursor *pCur)
160161
}
161162

162163
pCur->rowid++; // Read the next file
164+
165+
if (gbl_comdb2_files_sleep_secs_after_processing_llmeta
166+
&& (strcmp(fname, "comdb2_llmeta.dta") == 0)) {
167+
logmsg(LOGMSG_DEBUG, "%s:%d just processed llmeta. Sleeping for %d seconds\n",
168+
__func__, __LINE__, gbl_comdb2_files_sleep_secs_after_processing_llmeta);
169+
sleep(gbl_comdb2_files_sleep_secs_after_processing_llmeta);
170+
logmsg(LOGMSG_DEBUG, "%s:%d done sleeping\n", __func__, __LINE__);
171+
}
163172
}
164173

165174
return SQLITE_OK;

sqlite/ext/comdb2/files_util.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ static void set_chunk_size(db_file_t *f, size_t chunk_size)
121121
dbfile_set_chunk_size(f->info, chunk_size);
122122
}
123123

124-
125-
126124
static int read_dir(const char *dirname, db_file_t **files, int *count, char *file_pattern, size_t chunk_size)
127125
{
128126
struct dirent buf;

tests/bulkimport.test/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ else
66
include $(TESTSROOTDIR)/testcase.mk
77
endif
88
ifeq ($(TEST_TIMEOUT),)
9-
export TEST_TIMEOUT=5m
9+
export TEST_TIMEOUT=7m
1010
endif

tests/bulkimport.test/runit

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,29 @@ function test_bad_inputs_with_werror() {
353353
)
354354
}
355355

356+
function test_source_table_does_not_exist() {
357+
(
358+
# Given
359+
local dst_tbl=foo
360+
query_dst_db "create table $dst_tbl(i int)"
361+
trap "query_dst_db 'drop table $dst_tbl'" EXIT
362+
363+
# When
364+
err=$(query_dst_db "replace table $dst_tbl with LOCAL_$SRC_DBNAME.donut_exist" 2>&1)
365+
366+
# Then
367+
if (( $? == 0 )); then
368+
echo "FAIL: Expected import to fail"
369+
return 1
370+
fi
371+
372+
if ! echo $err | grep "Source table does not exist"; then
373+
echo "FAIL: Expected 'table does not exist' error"
374+
return 1
375+
fi
376+
)
377+
}
378+
356379
function test_resume_is_blocked() {
357380
(
358381
# Given
@@ -380,6 +403,116 @@ function test_resume_is_blocked() {
380403
)
381404
}
382405

406+
function test_src_db_table_dropped_during_import() {
407+
(
408+
# Given
409+
# create tables
410+
local src_tbl=foo dst_tbl=bar start_timestamp=$(date '+%Y/%m/%d %H:%M:%S')
411+
fixture_src_tbl_and_dst_tbl_have_same_schema $src_tbl $dst_tbl > /dev/null
412+
413+
# set tunables
414+
# the 30 second sleep gives the db time to flush logs reflecting the table drop
415+
set_src_tunable 'comdb2_files_sleep_secs_after_processing_llmeta 30'
416+
set_src_tunable 'logmsg level debug'
417+
418+
# teardown routines
419+
trap "set_src_tunable 'comdb2_files_sleep_secs_after_processing_llmeta 0';
420+
set_src_tunable 'logmsg level warn';
421+
query_dst_db 'drop table $dst_tbl'" EXIT
422+
423+
# start import and wait for the source db to sleep after
424+
# sending llmeta to the dst db
425+
query_dst_db "replace table $dst_tbl with LOCAL_$SRC_DBNAME.$src_tbl" 2> err.txt &
426+
waitpid=$!
427+
wait_for_src_trace "just processed llmeta" "$start_timestamp"
428+
429+
# When
430+
query_src_db "drop table $src_tbl"
431+
432+
# Then
433+
# We dropped the table between the point where it sent
434+
# llmeta and the point when it sent the txn logs.
435+
#
436+
# Therefore, the drop will be reflected in the txn logs,
437+
# which means that recovery will drop it from llmeta.
438+
#
439+
# So we expect the import to fail because
440+
# the source table will not exist.
441+
442+
if check_for_src_trace "read_next_chunk.*done sleeping" "$start_timestamp"; then
443+
echo "FAIL: Expected source database to still be sleeping. Test is buggy"
444+
return 1
445+
fi
446+
447+
if wait $waitpid; then
448+
echo "FAIL: Expected import to fail."
449+
return 1
450+
fi
451+
452+
if ! cat err.txt | grep "Source table does not exist"; then
453+
echo "FAIL: Expected 'table does not exist' error"
454+
return 1
455+
fi
456+
457+
if verify_eq $src_tbl $dst_tbl; then
458+
echo "FAIL: Expected tables to not match"
459+
return 1
460+
fi
461+
)
462+
}
463+
464+
function test_src_db_election_during_import() {
465+
(
466+
# Given
467+
# create tables
468+
local src_tbl=foo dst_tbl=bar start_timestamp=$(date '+%Y/%m/%d %H:%M:%S')
469+
fixture_src_tbl_and_dst_tbl_have_same_schema $src_tbl $dst_tbl > /dev/null
470+
471+
# set tunables
472+
set_src_tunable 'comdb2_files_sleep_secs_after_processing_llmeta 10'
473+
set_src_tunable 'logmsg level debug'
474+
475+
# teardown routines
476+
trap "set_src_tunable 'comdb2_files_sleep_secs_after_processing_llmeta 0';
477+
set_src_tunable 'logmsg level warn';
478+
query_src_db 'drop table $src_tbl';
479+
query_dst_db 'drop table $dst_tbl'" EXIT
480+
481+
482+
# start import and wait for the source db to sleep after
483+
# sending llmeta to the dst db
484+
query_dst_db "replace table $dst_tbl with LOCAL_$SRC_DBNAME.$src_tbl" &
485+
waitpid=$!
486+
wait_for_src_trace "just processed llmeta" "$start_timestamp"
487+
488+
# When
489+
downgrade_src_db
490+
491+
# Then
492+
493+
downgrade_rc=$?
494+
if (( downgrade_rc != 0 )); then
495+
echo "FAIL: Expected downgrade to succeed"
496+
return 1
497+
fi
498+
499+
if check_for_src_trace "read_next_chunk.*done sleeping" "$start_timestamp"; then
500+
echo "FAIL: Expected source database to still be sleeping. Test is buggy"
501+
return 1
502+
fi
503+
504+
if ! wait $waitpid; then
505+
echo "FAIL: Expected import to succeed"
506+
return 1
507+
fi
508+
509+
if ! verify_eq $src_tbl $dst_tbl; then
510+
echo "FAIL: Expected tables to match"
511+
return 1
512+
fi
513+
)
514+
}
515+
383516
function run_basic_test() {
384517
(
385518
# Given

tests/bulkimport.test/util.sh

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,14 @@ function failexit() {
3030
fi
3131
}
3232

33-
function query_src_db_opts() {
34-
query=$1
35-
opts=$2
36-
37-
cdb2sql ${SRC_CDB2_OPTIONS} ${opts} $SRC_DBNAME default "$query"
38-
}
39-
40-
function query_dst_db_opts() {
41-
query=$1
42-
opts=$2
43-
44-
cdb2sql ${DST_CDB2_OPTIONS} ${opts} $DST_DBNAME default "$query"
45-
}
46-
4733
function query_src_db() {
48-
query_src_db_opts "$1"
34+
query=$1
35+
cdb2sql ${SRC_CDB2_OPTIONS} $SRC_DBNAME default "$query"
4936
}
5037

5138
function query_dst_db() {
52-
query_dst_db_opts "$1"
39+
query=$1
40+
cdb2sql ${DST_CDB2_OPTIONS} $DST_DBNAME default "$query"
5341
}
5442

5543
function set_src_tunable() {
@@ -70,6 +58,29 @@ function set_dst_tunable() {
7058
done
7159
}
7260

61+
function check_for_src_trace() {
62+
local -r trace="$1" timestamp="$2"
63+
awk -v ts="${timestamp}" '$0 >= ts' ${TESTDIR}/logs/${SRC_DBNAME}* | grep "${trace}"
64+
}
65+
66+
function wait_for_src_trace() {
67+
local -r trace="$1" timestamp="$2"
68+
while ! check_for_src_trace "$trace" "$timestamp"; do
69+
sleep .1
70+
done
71+
}
72+
73+
function downgrade_src_db() {
74+
local master
75+
master=$(cdb2sql ${SRC_CDB2_OPTIONS} -tabs $SRC_DBNAME default 'SELECT host FROM comdb2_cluster WHERE is_master="Y"') || return 1
76+
cdb2sql --host ${master} ${SRC_CDB2_OPTIONS} $SRC_DBNAME "exec procedure sys.cmd.send('downgrade')" || return 1
77+
local new_master=${master}
78+
while [[ "${new_master}" == "${master}" ]]; do
79+
sleep 1
80+
new_master=$(cdb2sql ${SRC_CDB2_OPTIONS} -tabs $SRC_DBNAME default 'SELECT host FROM comdb2_cluster WHERE is_master="Y"') || return 1
81+
done
82+
}
83+
7384
function query_in_loop() {
7485
query_func=$1
7586
query=$2

0 commit comments

Comments
 (0)