Skip to content

Commit 1b0862f

Browse files
raakella1Ravi Nagarjun Akella
andauthored
Long running setup (#126)
* add scripts for setting up long running io test * improve io test logging --------- Co-authored-by: Ravi Nagarjun Akella <raakella1@$HOSTNAME>
1 parent 9555f6b commit 1b0862f

File tree

10 files changed

+152
-17
lines changed

10 files changed

+152
-17
lines changed

.jenkins/Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# ########## ####### ############
2+
FROM hub.tess.io/sds/sds_develop:7.x-latest
3+
LABEL description="Automated HomeBlocks compilation"
4+
5+
WORKDIR /output
6+
7+
RUN set -eux; \
8+
sed -i 's/master/latest/g' /etc/apt/sources.list; \
9+
apt-get update; \
10+
apt-get upgrade -y; \
11+
apt-get install iputils-ping; \
12+
apt-get install net-tools; \
13+
rm -rf /var/lib/apt/lists/*;
14+
15+
16+
# executables
17+
COPY test_volume_io /usr/local/bin/test_volume_io
18+
# scripts
19+
COPY io_test.py /usr/local/bin/scripts/io_test.py
20+
COPY long_running.py /usr/local/bin/scripts/long_running.py
21+
22+
23+
EXPOSE 5000
24+
# ########## ####### ############

conanfile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class HomeBlocksConan(ConanFile):
1111
name = "homeblocks"
12-
version = "2.1.2"
12+
version = "2.1.3"
1313
homepage = "https://github.com/eBay/HomeBlocks"
1414
description = "Block Store built on HomeStore"
1515
topics = ("ebay")
@@ -45,7 +45,7 @@ def build_requirements(self):
4545
self.test_requires("gtest/1.14.0")
4646

4747
def requirements(self):
48-
self.requires("homestore/[~6.18]@oss/master", transitive_headers=True)
48+
self.requires("homestore/[^6.20]@oss/master", transitive_headers=True)
4949
self.requires("iomgr/[^11.3]@oss/master", transitive_headers=True)
5050
self.requires("sisl/[^12.2]@oss/master", transitive_headers=True)
5151
self.requires("lz4/1.9.4", override=True)

src/lib/volume/index_fixed_table.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ class VolumeIndexTable {
2929
BtreeValue const& value) {
3030
auto lba = r_cast< const VolumeIndexKey& >(key).lba();
3131
auto& existing_value_vol_idx = r_cast< const VolumeIndexValue& >(existing_value);
32-
LOGINFO("Filter callback for lba {}, existing value: {}", lba, existing_value_vol_idx.blkid().to_string());
3332
blocks_info[lba].old_blkid = existing_value_vol_idx.blkid();
3433
blocks_info[lba].old_checksum = existing_value_vol_idx.checksum();
3534
return homestore::put_filter_decision::replace;

src/lib/volume/tests/test_common.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ SISL_OPTION_GROUP(
5252
"true or false"),
5353
(enable_crash, "", "enable_crash", "enable crash", ::cxxopts::value< bool >()->default_value("0"), ""),
5454
(app_mem_size, "", "app_mem_size", "app memory size", ::cxxopts::value< uint64_t >()->default_value("20"),
55+
"number"),
56+
(hs_chunk_size_mb, "", "hs_chunk_size_mb", "hs_chunk_size_mb", ::cxxopts::value< uint64_t >()->default_value("128"),
5557
"number"));
5658

5759
using namespace homeblocks;
@@ -175,7 +177,7 @@ class HBTestHelper {
175177
init_dev_list(true /*init_device*/);
176178

177179
LOGINFO("Starting HomeBlocks");
178-
homeblocks::HomeBlocksImpl::_hs_chunk_size = 128 * Mi;
180+
homeblocks::HomeBlocksImpl::_hs_chunk_size = SISL_OPTIONS["hs_chunk_size_mb"].as< uint64_t >() * Mi;
179181
// set_min_chunk_size(4 * Mi);
180182
app_ = std::make_shared< HBTestApplication >(*this);
181183
hb_ = init_homeblocks(std::weak_ptr< HBTestApplication >(app_));
@@ -309,6 +311,7 @@ class HBTestHelper {
309311
}
310312

311313
void remove_files() {
314+
if (SISL_OPTIONS.count("device_list")) { return; }
312315
for (const auto& fpath : dev_list_) {
313316
if (std::filesystem::exists(fpath)) {
314317
LOGINFO("Removing file {}", fpath);

src/lib/volume/tests/test_scripts/CMakeLists.txt

Whitespace-only changes.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python3
2+
## @file index_test.py
3+
import subprocess
4+
import argparse
5+
6+
7+
class TestFailedError(Exception):
8+
pass
9+
10+
11+
def run_test(options):
12+
cmd_opts = f"--gtest_filter=VolumeIOTest.LongRunningRandomIO --gtest_break_on_failure {options['log_mods']} --run_time={options['run_time']} --vol_size_gb={options['vol_size_gb']} --num_vols={options['num_vols']} --device_list {options['device_list']} --hs_chunk_size_mb={options['hs_chunk_size_mb']}"
13+
test_cmd = f"{options['dirpath']}/test_volume_io {cmd_opts}"
14+
print(f"Running command: {test_cmd}")
15+
try:
16+
subprocess.check_call(test_cmd, stderr=subprocess.STDOUT, shell=True)
17+
except subprocess.CalledProcessError as e:
18+
print(f"Test failed: {e}")
19+
raise TestFailedError(f"Test failed!")
20+
print("Test completed")
21+
22+
23+
def parse_arguments():
24+
# Create the parser
25+
parser = argparse.ArgumentParser(description='Parse command line options.')
26+
27+
# Add arguments with default values
28+
parser.add_argument('--dirpath', help='Directory path', default='.')
29+
parser.add_argument('--log_mods', help='Log modules', default='')
30+
parser.add_argument('--cp_timer_ms', help='cp_timer_ms', type=int, default=60000)
31+
parser.add_argument('--run_time', help='Run time in seconds', type=int, default=10)
32+
parser.add_argument('--vol_size_gb', help='vol_size_gb', type=int, default=500)
33+
parser.add_argument('--num_vols', help='num_vols', type=int, default=5)
34+
parser.add_argument('--device_list', help='Device list', default='')
35+
parser.add_argument('--init_device', help='Initialize device', type=bool, default=True)
36+
parser.add_argument('--use_file', help='Initialize device', action="store_true")
37+
parser.add_argument('--hs_chunk_size_mb', help='hs_chunk_size', type=int, default=2048)
38+
39+
# Parse the known arguments and ignore any unknown arguments
40+
args, unknown = parser.parse_known_args()
41+
42+
options = vars(args)
43+
44+
return options
45+
46+
47+
def long_runnig_io(options):
48+
print("Long running test started")
49+
if options['device_list'] == '':
50+
if not options['use_file']:
51+
print("No device list provided, use --use_file flag to use a file as a device")
52+
exit(1)
53+
# fallocate a file to use as a device
54+
options['device_list'] = f"{options['dirpath']}/io_long_running_device"
55+
dev_size = options['vol_size_gb'] * 1.5 # Ensure the device is larger than the volume size
56+
subprocess.check_call(f"fallocate -l {dev_size}G {options['device_list']}", shell=True)
57+
print(f"Created device: {options['device_list']} of size {dev_size} GB")
58+
print(f"options: {options}")
59+
run_test(options)
60+
# remove the device file after the test
61+
if "io_long_running_device" in options['device_list']:
62+
subprocess.check_call(f"rm -f {options['device_list']}", shell=True)
63+
print(f"Removed device: {options['device_list']}")
64+
print("Long running test completed")
65+
66+
67+
def long_running(*args):
68+
options = parse_arguments()
69+
long_runnig_io(options)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
## @file long_running.py
3+
#
4+
5+
import sys
6+
import argparse
7+
import io_test
8+
9+
10+
def parse_arguments():
11+
parser = argparse.ArgumentParser(description='Run long-running tests.')
12+
parser.add_argument('--test_suit', help='Test suits to run', default='io_long_running')
13+
args, service_args = parser.parse_known_args()
14+
return args, service_args
15+
16+
test_functions = {
17+
'io_long_running': io_test.long_running
18+
}
19+
20+
def main():
21+
args, service_args = parse_arguments()
22+
23+
# Check if the test_suits argument is provided and is valid
24+
if args.test_suit in test_functions:
25+
test_functions[args.test_suit](service_args)
26+
else:
27+
print(f"Unknown test suite: {args.test_suit}")
28+
print(f"Available tests: {', '.join(test_functions.keys())}")
29+
sys.exit(1)
30+
31+
32+
if __name__ == "__main__":
33+
main()

src/lib/volume/tests/test_volume_io.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,12 @@ TEST_F(VolumeIOTest, LongRunningRandomIO) {
554554
total_writes += get_total_writes();
555555
std::chrono::duration< double > elapsed = std::chrono::high_resolution_clock::now() - start_time;
556556
auto elapsed_seconds = static_cast< uint64_t >(elapsed.count());
557-
LOGINFO("total_read={} total_write={} elapsed={}", total_reads, total_writes, elapsed_seconds);
558-
557+
static uint64_t log_pct = 0;
558+
if (auto done_pct = (run_time > 0) ? (elapsed_seconds * 100) / run_time : 100; done_pct > log_pct) {
559+
LOGINFO("total_read={} total_write={} elapsed={}, done pct={}", total_reads, total_writes, elapsed_seconds, done_pct);
560+
log_pct += 5;
561+
}
562+
559563
if (elapsed_seconds >= run_time) { break; }
560564
} while (true);
561565
}
@@ -585,9 +589,10 @@ TEST_F(VolumeIOTest, LongRunningSequentialIO) {
585589
total_writes += get_total_writes();
586590
std::chrono::duration< double > elapsed = std::chrono::high_resolution_clock::now() - start_time;
587591
auto elapsed_seconds = static_cast< uint64_t >(elapsed.count());
588-
if (elapsed_seconds % 2 == 0) {
589-
LOGINFO("total_read={} total_write={} lba={} elapsed={}", total_reads, total_writes, cur_lba,
590-
elapsed_seconds);
592+
static uint64_t log_pct = 0;
593+
if (auto done_pct = (run_time > 0) ? (elapsed_seconds * 100) / run_time : 100; done_pct > log_pct) {
594+
LOGINFO("total_read={} total_write={} elapsed={}, done pct={}", total_reads, total_writes, elapsed_seconds, done_pct);
595+
log_pct += 5;
591596
}
592597

593598
if (((cur_lba + nblks) * g_page_size) >= volume_size) {

src/lib/volume/volume_chunk_selector.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ homestore::cshared< Chunk > VolumeChunkSelector::select_chunk(homestore::blk_cou
141141
if (chunk && chunk->available_blks() > 0) { return chunk->get_internal_chunk(); }
142142
}
143143

144-
LOGI("Waiting to allocate more chunks active={} total={}", volc->num_active_chunks.load(),
144+
LOGT("Waiting to allocate more chunks active={} total={}", volc->num_active_chunks.load(),
145145
volc->max_num_chunks);
146-
dump_chunks();
146+
LOGT("{}", dump_chunks());
147147
std::this_thread::sleep_for(std::chrono::milliseconds(100));
148148
} while (true);
149149

@@ -184,7 +184,7 @@ void VolumeChunkSelector::resize_volume_num_chunks(homestore::blk_count_t nblks,
184184
}
185185

186186
// Spawn background task to create new chunks.
187-
LOGI("Initiating op to resize num chunks for volume={} available={} total={}", volc->ordinal, available_blks,
187+
LOGD("Initiating op to resize num chunks for volume={} available={} total={}", volc->ordinal, available_blks,
188188
total_blks);
189189
iomanager.run_on_forget(iomgr::reactor_regex::random_worker, [volc, this]() mutable {
190190
std::string str;
@@ -213,7 +213,7 @@ void VolumeChunkSelector::resize_volume_num_chunks(homestore::blk_count_t nblks,
213213
// Update the number of active chunks and compelete the resize operation.
214214
volc->num_active_chunks = indx;
215215
resize_op.store(ResizeOp::Idle);
216-
LOGI("Resize op done. Allocated more chunks for volume={} total={} new={} new_chunks={}", volc->ordinal,
216+
LOGD("Resize op done. Allocated more chunks for volume={} total={} new={} new_chunks={}", volc->ordinal,
217217
volc->num_active_chunks.load(), chunks.size(), str);
218218
});
219219
}
@@ -359,18 +359,20 @@ void VolumeChunkSelector::dump_per_pdev_chunks() const {
359359
}
360360
}
361361

362-
void VolumeChunkSelector::dump_chunks() const {
362+
std::string VolumeChunkSelector::dump_chunks() const {
363363
std::lock_guard lock(m_chunk_sel_mutex);
364+
std::string str;
364365
for (uint32_t i = 0; i < m_volume_chunks.size(); i++) {
365366
if (!m_volume_chunks[i]) { continue; }
366-
std::string str;
367+
fmt::format_to(std::back_inserter(str), "volume={} num_chunks={} chunks=", i, m_volume_chunks[i]->m_chunks.size());
367368
for (const auto& chunk : m_volume_chunks[i]->m_chunks) {
368369
if (!chunk) { continue; }
369370
fmt::format_to(std::back_inserter(str), "{}({}/{}) ", chunk->get_chunk_id(), chunk->available_blks(),
370371
chunk->get_total_blks());
371372
}
372-
LOGI("volume={} num_chunks={} chunks={}", i, m_volume_chunks[i]->m_chunks.size(), str);
373+
fmt::format_to(std::back_inserter(str), "\n");
373374
}
375+
return str;
374376
}
375377

376378
} // namespace homeblocks

src/lib/volume/volume_chunk_selector.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class VolumeChunkSelector : public homestore::ChunkSelector {
8888
std::vector< shared< HBChunk > > allocate_resize_chunks_from_pdev(uint32_t pdev, uint64_t num_chunks);
8989
void resize_volume_num_chunks(homestore::blk_count_t nblks, shared< VolumeChunksInfo > volc);
9090
void dump_per_pdev_chunks() const;
91-
void dump_chunks() const;
91+
std::string dump_chunks() const;
9292

9393
private:
9494
enum class ResizeOp {

0 commit comments

Comments
 (0)