Skip to content

Commit 63c5fc4

Browse files
committed
Add repro test_fp_num_tuples_out_of_bounds_bug_trunk_build_filters() and instrumentation.
1 parent 08722f1 commit 63c5fc4

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

src/trunk.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,7 @@ struct trunk_compact_bundle_req {
724724
uint64 tuples_reclaimed;
725725
uint64 kv_bytes_reclaimed;
726726
fp_hdr breq_fingerprint;
727+
uint64 num_tuples;
727728
uint64 enq_line; // Where task was enqueued
728729
};
729730

@@ -3610,6 +3611,7 @@ typedef struct trunk_filter_scratch {
36103611
uint16 value[TRUNK_MAX_PIVOTS];
36113612
routing_filter filter[TRUNK_MAX_PIVOTS];
36123613
fp_hdr filter_fingerprint;
3614+
uint64 num_tuples;
36133615
} trunk_filter_req;
36143616

36153617
static inline void
@@ -3813,6 +3815,16 @@ trunk_build_filters(trunk_handle *spl,
38133815
trunk_process_generation_to_fp_bounds(
38143816
spl, compact_req, generation, &fp_start, &fp_end);
38153817

3818+
debug_assert(
3819+
(fp_start < fingerprint_ntuples(&filter_req->filter_fingerprint)),
3820+
"Requested fp_start=%u should be < "
3821+
"fingerprint for %lu tuples."
3822+
" Compact bundle req type=%d, enqueued at line=%lu",
3823+
fp_start,
3824+
fingerprint_ntuples(&filter_req->filter_fingerprint),
3825+
compact_req->type,
3826+
compact_req->enq_line);
3827+
38163828
uint32 *fp_arr =
38173829
fingerprint_nth(&filter_req->filter_fingerprint, fp_start);
38183830

src/util.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,27 @@ fingerprint_line(fp_hdr *fp)
401401
}
402402

403403
/* Return the start of the n'th piece (tuple) in the fingerprint array. */
404+
#define fingerprint_nth(dst, src) \
405+
fingerprint_do_nth((dst), (src), __FILE__, __LINE__)
406+
404407
static inline uint32 *
405-
fingerprint_nth(fp_hdr *fp, uint32 nth_tuple)
408+
fingerprint_do_nth(fp_hdr *fp,
409+
uint32 nth_tuple,
410+
const char *file,
411+
const int line)
406412
{
407413
// Cannot ask for a location beyond size of fingerprint array
408414
debug_assert((nth_tuple < fingerprint_ntuples(fp)),
409-
"nth_tuple=%u, ntuples=%lu, init-line=%u",
415+
"[%s:%d] nth_tuple=%u, ntuples=%lu, init'ed at line=%u"
416+
", copy_line=%u, alias_line=%u, move_line=%u ",
417+
file,
418+
line,
410419
nth_tuple,
411420
fingerprint_ntuples(fp),
412-
fingerprint_line(fp));
421+
fp->init_line,
422+
fp->copy_line,
423+
fp->alias_line,
424+
fp->move_line);
413425

414426
return ((uint32 *)memfrag_start(&fp->mf) + nth_tuple);
415427
}
@@ -455,6 +467,7 @@ fingerprint_do_alias(fp_hdr *dst, const fp_hdr *src, uint32 line)
455467
dst->ntuples = src->ntuples;
456468
dst->alias_line = line;
457469

470+
// Update alias refcounts
458471
debug_code(dst->num_aliases++);
459472
debug_code(dst->srcfp = (fp_hdr *)src;);
460473
debug_code(dst->srcfp->num_aliases++);
@@ -480,8 +493,10 @@ fingerprint_do_unalias(fp_hdr *dst, uint32 line)
480493
// (init_line != last_line) => 'unalias' was done
481494
dst->alias_line = line;
482495

496+
// Update alias refcounts
483497
debug_code(dst->num_aliases--);
484498
debug_code(dst->srcfp->num_aliases--);
499+
debug_code(dst->srcfp->alias_line = line);
485500
debug_code(dst->srcfp = ((dst->num_aliases == 0) ? NULL : dst->srcfp));
486501

487502
return (uint32 *)memfrag_start(&dst->mf);

tests/unit/large_inserts_stress_test.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,74 @@ CTEST2(large_inserts_stress, test_random_keys_random_values_threaded)
585585
close(random_val_fd);
586586
}
587587

588+
CTEST2(large_inserts_stress,
589+
test_fp_num_tuples_out_of_bounds_bug_trunk_build_filters)
590+
{
591+
char key_data[TEST_KEY_SIZE];
592+
char val_data[TEST_VALUE_SIZE];
593+
594+
uint64 start_key = 0;
595+
596+
uint64 start_time = platform_get_timestamp();
597+
598+
threadid thread_idx = platform_get_tid();
599+
600+
// Test is written to insert multiples of millions per thread.
601+
ASSERT_EQUAL(0, (data->num_inserts % MILLION));
602+
603+
platform_default_log("%s()::%d:Thread-%-lu inserts %lu (%lu million)"
604+
", sequential key, sequential value, "
605+
"KV-pairs starting from %lu ...\n",
606+
__func__,
607+
__LINE__,
608+
thread_idx,
609+
data->num_inserts,
610+
(data->num_inserts / MILLION),
611+
start_key);
612+
613+
uint64 ictr = 0;
614+
uint64 jctr = 0;
615+
616+
bool verbose_progress = TRUE;
617+
memset(val_data, 'V', sizeof(val_data));
618+
uint64 val_len = sizeof(val_data);
619+
620+
for (ictr = 0; ictr < (data->num_inserts / MILLION); ictr++) {
621+
for (jctr = 0; jctr < MILLION; jctr++) {
622+
623+
uint64 id = (start_key + (ictr * MILLION) + jctr);
624+
625+
// Generate sequential key data
626+
snprintf(key_data, sizeof(key_data), "%lu", id);
627+
uint64 key_len = strlen(key_data);
628+
629+
slice key = slice_create(key_len, key_data);
630+
slice val = slice_create(val_len, val_data);
631+
632+
int rc = splinterdb_insert(data->kvsb, key, val);
633+
ASSERT_EQUAL(0, rc);
634+
}
635+
if (verbose_progress) {
636+
platform_default_log(
637+
"%s()::%d:Thread-%lu Inserted %lu million KV-pairs ...\n",
638+
__func__,
639+
__LINE__,
640+
thread_idx,
641+
(ictr + 1));
642+
}
643+
}
644+
uint64 elapsed_ns = platform_timestamp_elapsed(start_time);
645+
646+
platform_default_log("%s()::%d:Thread-%lu Inserted %lu million KV-pairs in "
647+
"%lu s, %lu rows/s\n",
648+
__func__,
649+
__LINE__,
650+
thread_idx,
651+
ictr, // outer-loop ends at #-of-Millions inserted
652+
NSEC_TO_SEC(elapsed_ns),
653+
(data->num_inserts / NSEC_TO_SEC(elapsed_ns)));
654+
}
655+
588656
/*
589657
* ----------------------------------------------------------------------------
590658
* do_inserts_n_threads() - Driver function that will fire-up n-threads to

0 commit comments

Comments
 (0)