From cfc911df498cf4b506c508563620539e7a81a143 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Tue, 18 Dec 2018 16:22:08 -0600 Subject: [PATCH 01/16] cli: catch boost::program_options parsing errors Signed-off-by: Victor Sui --- src/zlog.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 24e89ee..8a2f43b 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -31,15 +31,19 @@ int main(int argc, char **argv) popts.add("command", -1); po::variables_map vm; - po::store(po::command_line_parser(argc, argv).options(opts).positional(popts).run(), vm); + try { + po::store(po::command_line_parser(argc, argv).options(opts).positional(popts).run(), vm); + po::notify(vm); + } catch (const boost::program_options::error &exception) { + std::cerr << exception.what() << std::endl; + return 1; + } if (vm.count("help")) { std::cout << opts << std::endl; return 1; } - po::notify(vm); - zlog::Options options; options.backend_name = backend_name; From 0d777be7bdd61d198c86abb3fe0d554e8bd82f2c Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Tue, 18 Dec 2018 18:53:47 -0600 Subject: [PATCH 02/16] cli: log command wip --- src/zlog.cc | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/src/zlog.cc b/src/zlog.cc index 8a2f43b..98b201b 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -3,12 +3,15 @@ #include #include #include "zlog/backend.h" +#include "zlog/log.h" #include "zlog/options.h" #include "libzlog/striper.h" #include "proto/zlog.pb.h" namespace po = boost::program_options; +int handle_log(std::vector, std::shared_ptr); + int main(int argc, char **argv) { std::vector command; @@ -27,6 +30,7 @@ int main(int argc, char **argv) ("command", po::value>(&command), "command") ; + // This gives us a vector of the command line arguments with flags removed po::positional_options_description popts; popts.add("command", -1); @@ -63,6 +67,13 @@ int main(int argc, char **argv) return ret; } + if (command.size() > 0) { + if (command[0] == "log") { + auto subcommand = std::vector(command.begin() + 1, command.end()); + return handle_log(subcommand, backend); + } + } + std::string hoid; std::string prefix; ret = backend->OpenLog(log_name, &hoid, &prefix); @@ -107,3 +118,169 @@ int main(int argc, char **argv) return 0; } + +/* + * Handles log commands and returns an exit code. The accepted commands are + * - create + * - append + * - dump + * - trim + * - fill + * - rename + * + * @param command the command to execute + * @param backend the backend to use + * + * @return exit code + */ +int handle_log(std::vector command, std::shared_ptr backend) { + const static std::map usages = { + { "create", "zlog log create " }, + { "append", "zlog log append " }, + { "dump", "zlog log dump " }, + { "trim", "zlog log trim " }, + { "fill", "zlog log fill " }, + { "rename", "zlog log rename " }, + }; + + if (command.size() == 0 || usages.find(command[0]) == usages.end()) { + std::cerr << "usage:" << std::endl; + for (const auto &usage : usages) { + std::cerr << usage.second << std::endl; + } + return 1; + } + + if (command[0] == "create") { + if (command.size() != 2) { // create + std::cerr << usages.at("create") << std::endl; + return 1; + } + std::string hoid, prefix; + int ret = backend->CreateLog(command[1], "", &hoid, &prefix); + switch (ret) { + case 0: + break; + case -EEXIST: + std::cerr << "error: log name already exists" << std::endl; + return ret; + case -EINVAL: + std::cerr << "error: invalid input" << std::endl; + return ret; + default: + std::cerr << "error: unknown error" << std::endl; + return ret; + } + std::cout << hoid << std::endl << prefix << std::endl; + return 0; + } + + // The rest of the commands need an opened log + zlog::Log *plog; + zlog::Options options; + options.backend = backend; + int ret = zlog::Log::Open(options, command[1], &plog); + switch (ret) { + case 0: + break; + case -ENOENT: + std::cerr << "error: no log named \"" + command[1] + "\"" << std::endl; + return ret; + case -EINVAL: + std::cerr << "error: invalid input" << std::endl; + default: + std::cerr << "error: unknown error " << ret << std::endl; + return ret; + } + std::unique_ptr log(plog); + + if (command[0] == "append") { + if (command.size() != 2) { // append + std::cerr << usages.at("append") << std::endl; + return 1; + } + uint64_t tail; + int ret = log->CheckTail(&tail); + if (ret != 0) { + std::cerr << "log::CheckTail " << ret << std::endl; + return ret; + } + std::string data; + while (std::getline(std::cin, data)) { // Extra lines at end of file possible + int ret = log->Append(data, &tail); + if (ret != 0) { + std::cerr << "log::Append " << ret << std::endl; + return ret; + } + } + return 0; + } else if (command[0] == "dump") { + if (command.size() != 2) { // dump + std::cerr << usages.at("dump") << std::endl; + return 1; + } + uint64_t tail; + int ret = log->CheckTail(&tail); + if (ret != 0) { + std::cerr << "log::CheckTail " << ret << std::endl; + return ret; + } + std::string data; + for (uint64_t i = 0; i < tail; ++i) { + int ret = log->Read(i, &data); + if (ret != 0) { + std::cerr << "log::Read " << ret << std::endl; + return ret; + } + std::cout << data << std::endl; + } + return 0; + } else if (command[0] == "trim") { + if (command.size() != 3) { // trim + std::cerr << usages.at("trim") << std::endl; + return 1; + } + uint64_t pos; + try { + pos = std::stoul(command[2]); + } catch (const std::invalid_argument &e) { + std::cerr << e.what() << std::endl; + return 1; + } + int ret = log->Trim(pos); + if (ret != 0) { + std::cerr << "log::Trim " << ret << std::endl; + } + return ret; + } else if (command[0] == "fill") { + if (command.size() != 3) { // fill + std::cerr << usages.at("fill") << std::endl; + return 1; + } + uint64_t pos; + try { + pos = std::stoul(command[2]); + } catch (const std::invalid_argument &e) { + std::cerr << e.what() << std::endl; + return 1; + } + int ret = log->Fill(pos); + if (ret != 0) { + std::cerr << "log::Fill " << ret << std::endl; + } + return ret; + } else if (command[0] == "rename") { + if (command.size() != 3) { // rename + std::cerr << usages.at("rename") << std::endl; + return 1; + } + std::cerr << "Not implemented" << std::endl; + return 0; + } + // Should never reach here, but just to be safe + std::cerr << "usage:" << std::endl; + for (const auto &usage : usages) { + std::cerr << usage.second << std::endl; + } + return 1; +} \ No newline at end of file From 623067593facb6de9fe2e2c783456e0abb84dace Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 13:45:28 -0600 Subject: [PATCH 03/16] cli: add `head list` and `link list` Signed-off-by: Victor Sui --- src/zlog.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/zlog.cc b/src/zlog.cc index 98b201b..42d9957 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -74,6 +74,30 @@ int main(int argc, char **argv) } } + if (command == std::vector{ "link", "list" }) { + std::vector links; + int ret = backend->ListLinks(links); + if (ret != 0) { + std::cerr << "backend::ListLinks " << ret << std::endl; + return ret; + } + for (const auto &link : links) { + std::cout << link << std::endl; + } + return 0; + } else if (command == std::vector{ "head", "list" }) { + std::vector heads; + int ret = backend->ListHeads(heads); + if (ret != 0) { + std::cerr << "backend::ListHeads " << ret << std::endl; + return ret; + } + for (const auto &head : heads) { + std::cout << head << std::endl; + } + return 0; + } + std::string hoid; std::string prefix; ret = backend->OpenLog(log_name, &hoid, &prefix); From 2bae9329233ac568a230515a49c633285ba7b683 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 14:18:40 -0600 Subject: [PATCH 04/16] cli: modify append interface Makes append pass in a string to append via command or copy a file to it. The way this was done was very hacky in order to play nice with boost::program_options, so we will probably want to fix this up/not use program_options in the future Signed-off-by: Victor Sui --- src/zlog.cc | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 42d9957..fb2296e 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "zlog/backend.h" @@ -10,7 +11,7 @@ namespace po = boost::program_options; -int handle_log(std::vector, std::shared_ptr); +int handle_log(std::vector, std::shared_ptr, std::string); int main(int argc, char **argv) { @@ -19,6 +20,7 @@ int main(int argc, char **argv) std::string backend_name; std::string pool; std::string db_path; + std::string input_filename; po::options_description opts("Benchmark options"); opts.add_options() @@ -28,6 +30,7 @@ int main(int argc, char **argv) ("pool", po::value(&pool)->default_value("zlog"), "pool (ceph)") ("db-path", po::value(&db_path)->default_value("/tmp/zlog.bench.db"), "db path (lmdb)") ("command", po::value>(&command), "command") + ("input-file,i", po::value(&input_filename), "input filename for log append") ; // This gives us a vector of the command line arguments with flags removed @@ -70,7 +73,7 @@ int main(int argc, char **argv) if (command.size() > 0) { if (command[0] == "log") { auto subcommand = std::vector(command.begin() + 1, command.end()); - return handle_log(subcommand, backend); + return handle_log(subcommand, backend, input_filename); } } @@ -152,15 +155,16 @@ int main(int argc, char **argv) * - fill * - rename * - * @param command the command to execute - * @param backend the backend to use + * @param command the command to execute + * @param backend the backend to use + * @param filename the input filename for append commands * * @return exit code */ -int handle_log(std::vector command, std::shared_ptr backend) { +int handle_log(std::vector command, std::shared_ptr backend, std::string filename) { const static std::map usages = { { "create", "zlog log create " }, - { "append", "zlog log append " }, + { "append", "zlog log append \nzlog log append -i " }, { "dump", "zlog log dump " }, { "trim", "zlog log trim " }, { "fill", "zlog log fill " }, @@ -219,25 +223,38 @@ int handle_log(std::vector command, std::shared_ptr std::unique_ptr log(plog); if (command[0] == "append") { - if (command.size() != 2) { // append - std::cerr << usages.at("append") << std::endl; - return 1; - } uint64_t tail; int ret = log->CheckTail(&tail); if (ret != 0) { std::cerr << "log::CheckTail " << ret << std::endl; return ret; } - std::string data; - while (std::getline(std::cin, data)) { // Extra lines at end of file possible - int ret = log->Append(data, &tail); + if (command.size() == 2 && filename != "") { // append with input file + std::ifstream input_file; + input_file.open(filename); + if (!input_file.is_open()) { + std::cerr << "no such file" << std::endl; + return 1; + } + std::string line; + while (std::getline(input_file, line)) { + int ret = log->Append(line, &tail); + if (ret != 0) { + std::cerr << "log::Append " << ret << std::endl; + return ret; + } + } + return 0; + } else if (command.size() == 3) { // append + int ret = log->Append(command[2], &tail); if (ret != 0) { std::cerr << "log::Append " << ret << std::endl; - return ret; } + return ret; + } else { + std::cerr << usages.at("append") << std::endl; + return 1; } - return 0; } else if (command[0] == "dump") { if (command.size() != 2) { // dump std::cerr << usages.at("dump") << std::endl; From 419ecb8992b3859e89752c5fcbdd026ed0c09f6e Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 14:22:14 -0600 Subject: [PATCH 05/16] cli: remove rename Will do this later Signed-off-by: Victor Sui --- src/zlog.cc | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index fb2296e..52a603a 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -153,7 +153,6 @@ int main(int argc, char **argv) * - dump * - trim * - fill - * - rename * * @param command the command to execute * @param backend the backend to use @@ -168,7 +167,6 @@ int handle_log(std::vector command, std::shared_ptr { "dump", "zlog log dump " }, { "trim", "zlog log trim " }, { "fill", "zlog log fill " }, - { "rename", "zlog log rename " }, }; if (command.size() == 0 || usages.find(command[0]) == usages.end()) { @@ -310,14 +308,8 @@ int handle_log(std::vector command, std::shared_ptr std::cerr << "log::Fill " << ret << std::endl; } return ret; - } else if (command[0] == "rename") { - if (command.size() != 3) { // rename - std::cerr << usages.at("rename") << std::endl; - return 1; - } - std::cerr << "Not implemented" << std::endl; - return 0; } + // Should never reach here, but just to be safe std::cerr << "usage:" << std::endl; for (const auto &usage : usages) { From af9bf8b100e9001e8ad4836224bacc7bed711291 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 14:24:45 -0600 Subject: [PATCH 06/16] cli: remove dead code Signed-off-by: Victor Sui --- src/zlog.cc | 48 +++++------------------------------------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 52a603a..231163e 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -101,49 +101,11 @@ int main(int argc, char **argv) return 0; } - std::string hoid; - std::string prefix; - ret = backend->OpenLog(log_name, &hoid, &prefix); - if (ret) { - std::cerr << "backend::openlog " << ret << std::endl; - return ret; - } - - uint64_t epoch = 1; - while (true) { - std::map views; - ret = backend->ReadViews(hoid, epoch, 1, &views); - if (ret) { - std::cerr << "read views error " << ret << std::endl; - return ret; - } - - if (views.empty()) { - break; - } - - assert(views.size() == 1u); - auto it = views.find(epoch); - assert(it != views.end()); - - zlog_proto::View view_src; - if (!view_src.ParseFromString(it->second)) { - assert(0); - exit(1); - } - - auto view = std::make_shared(prefix, it->first, view_src); - - std::cout << "view@" << view->epoch() << std::endl; - for (auto it : view->object_map.stripes()) { - std::cout << " stripe@" << it.second.id() << " [" << it.first - << ", " << it.second.max_position() << "]" << std::endl; - } - - epoch++; - } - - return 0; + std::cerr << "usage:" << std::endl + << "zlog log ..." << std::endl + << "zlog link list" << std::endl + << "zlog head list" << std::endl; + return 1; } /* From 0d784867d54fcc012e635068819cecb643166830 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 14:40:11 -0600 Subject: [PATCH 07/16] cli: dump log number and first eighty bytes in hex Signed-off-by: Victor Sui --- src/zlog.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/zlog.cc b/src/zlog.cc index 231163e..24c090b 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -233,7 +233,11 @@ int handle_log(std::vector command, std::shared_ptr std::cerr << "log::Read " << ret << std::endl; return ret; } - std::cout << data << std::endl; + std::cout << i << ": "; + for (char c : data.substr(0, 80)) { + std::cout << std::hex << static_cast(c); + } + std::cout << std::endl; } return 0; } else if (command[0] == "trim") { From 0f8718d9175a18d3bff242fd1d15bee4672340bc Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 15:06:46 -0600 Subject: [PATCH 08/16] cli: append file as single log entry Signed-off-by: Victor Sui --- src/zlog.cc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 24c090b..49a24af 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -190,21 +190,18 @@ int handle_log(std::vector command, std::shared_ptr return ret; } if (command.size() == 2 && filename != "") { // append with input file - std::ifstream input_file; - input_file.open(filename); - if (!input_file.is_open()) { + std::ifstream ifs(filename); + if (!ifs.is_open()) { std::cerr << "no such file" << std::endl; return 1; } - std::string line; - while (std::getline(input_file, line)) { - int ret = log->Append(line, &tail); - if (ret != 0) { - std::cerr << "log::Append " << ret << std::endl; - return ret; - } + std::string content( (std::istreambuf_iterator(ifs) ), + (std::istreambuf_iterator() ) ); + int ret = log->Append(content, &tail); + if (ret != 0) { + std::cerr << "log::Append " << ret << std::endl; } - return 0; + return ret; } else if (command.size() == 3) { // append int ret = log->Append(command[2], &tail); if (ret != 0) { From 94fcc3e74c5cbbddefae9d347994975da265815a Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 15:08:26 -0600 Subject: [PATCH 09/16] cli: left-pad hex on log dump Signed-off-by: Victor Sui --- src/zlog.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zlog.cc b/src/zlog.cc index 49a24af..32c3b2d 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -232,7 +233,7 @@ int handle_log(std::vector command, std::shared_ptr } std::cout << i << ": "; for (char c : data.substr(0, 80)) { - std::cout << std::hex << static_cast(c); + std::cout << std::setfill('0') << std::setw(2) << std::hex << static_cast(c); } std::cout << std::endl; } From fc9035f8625af6eb0beed859bdd0de766ff014a1 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 21:47:38 -0600 Subject: [PATCH 10/16] cli: add test Signed-off-by: Victor Sui --- ci/cli-test.sh | 39 +++++++++++++++++++++++++++++++++++++++ ci/test.sh | 6 ++++++ 2 files changed, 45 insertions(+) create mode 100755 ci/cli-test.sh diff --git a/ci/cli-test.sh b/ci/cli-test.sh new file mode 100755 index 0000000..7920a48 --- /dev/null +++ b/ci/cli-test.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e +set -x + +CLI_CMD=./zlog +LMDB_DIR=$(mktemp -d) + +INPUT_FILE=$(mktemp) +OUTPUT_FILE=$(mktemp) +EXPECTED_FILE=$(mktemp) +trap "rm -rf ${LMDB_DIR} ${INPUT_FILE} ${OUTPUT_FILE} ${EXPECTED_FILE}" exit + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log create testlog +! ${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log create testlog + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'just a lil test' +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'and another' +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'one more and were done' + +echo 'arthur willey!' >> ${INPUT_FILE} +echo 'nautili hunter' >> ${INPUT_FILE} +echo 'abcdefghijlmno' >> ${INPUT_FILE} + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog -i ${INPUT_FILE} + +echo '0: 6a7573742061206c696c2074657374' >> ${EXPECTED_FILE} +echo '1: 616e6420616e6f74686572' >> ${EXPECTED_FILE} +echo '2: 6f6e65206d6f726520616e64207765726520646f6e65' >> ${EXPECTED_FILE} +echo '3: 6172746875722077696c6c6579210a6e617574696c692068756e7465720a6162636465666768696a6c6d6e6f0a' >> ${EXPECTED_FILE} + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log dump testlog >> ${OUTPUT_FILE} + +diff ${EXPECTED_FILE} ${OUTPUT_FILE} + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log fill testlog 30 +! ${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log fill testlog 1 + +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log trim testlog 2 + diff --git a/ci/test.sh b/ci/test.sh index 15c263e..b6e25e3 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -100,3 +100,9 @@ if [[ "$OSTYPE" != "darwin"* && "$JNI" == "ON" ]]; then popd fi + +# test cli +pushd ${BUILD_DIR} +./cli-test.sh +popd ${BUILD_DIR} + From 07a1256a3a19801cb0e9fff58bbe12f15b0e1299 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Wed, 19 Dec 2018 23:07:59 -0600 Subject: [PATCH 11/16] cli: fix test path Signed-off-by: Victor Sui --- ci/cli-test.sh | 2 +- ci/test.sh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ci/cli-test.sh b/ci/cli-test.sh index 7920a48..b9e31b4 100755 --- a/ci/cli-test.sh +++ b/ci/cli-test.sh @@ -2,7 +2,7 @@ set -e set -x -CLI_CMD=./zlog +CLI_CMD=zlog LMDB_DIR=$(mktemp -d) INPUT_FILE=$(mktemp) diff --git a/ci/test.sh b/ci/test.sh index b6e25e3..9fddabb 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -102,7 +102,6 @@ if [[ "$OSTYPE" != "darwin"* && "$JNI" == "ON" ]]; then fi # test cli -pushd ${BUILD_DIR} -./cli-test.sh -popd ${BUILD_DIR} +export PATH +${ZLOG_DIR}/ci/cli-test.sh From 3c36f4fdb5480f4e11a81074cf123372d33ab6fb Mon Sep 17 00:00:00 2001 From: Noah Watkins Date: Wed, 19 Dec 2018 21:45:34 -0800 Subject: [PATCH 12/16] cli: install zlog cli tool Signed-off-by: Noah Watkins --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64bfe49..cd513a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,3 +63,4 @@ target_link_libraries(zlog ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_SYSTEM_LIBRARY} ) +install(TARGETS zlog DESTINATION bin) From 42f9f2930df2c392b6e730f7010bf40713c99ae6 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Thu, 20 Dec 2018 09:45:04 -0600 Subject: [PATCH 13/16] cli: prevent segfault when reading log name Signed-off-by: Victor Sui --- src/zlog.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 32c3b2d..0a82d1c 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -132,7 +132,7 @@ int handle_log(std::vector command, std::shared_ptr { "fill", "zlog log fill " }, }; - if (command.size() == 0 || usages.find(command[0]) == usages.end()) { + if (command.size() < 2 || usages.find(command[0]) == usages.end()) { std::cerr << "usage:" << std::endl; for (const auto &usage : usages) { std::cerr << usage.second << std::endl; @@ -280,4 +280,4 @@ int handle_log(std::vector command, std::shared_ptr std::cerr << usage.second << std::endl; } return 1; -} \ No newline at end of file +} From 91c2c1232756df4f43cced54f2bd0103c84b7381 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Thu, 20 Dec 2018 10:03:55 -0600 Subject: [PATCH 14/16] cli: better error handle on read Signed-off-by: Victor Sui --- src/zlog.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/zlog.cc b/src/zlog.cc index 0a82d1c..3f21a8d 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -227,9 +227,18 @@ int handle_log(std::vector command, std::shared_ptr std::string data; for (uint64_t i = 0; i < tail; ++i) { int ret = log->Read(i, &data); - if (ret != 0) { - std::cerr << "log::Read " << ret << std::endl; - return ret; + switch (ret) { + case 0: + break; + case -ENODATA: + std::cerr << i << ": invalidated" << std::endl; + continue; + case -ERANGE: + std::cerr << i << ": free" << std::endl; + continue; + default: + std::cerr << "log::Read " << ret << std::endl; + return ret; } std::cout << i << ": "; for (char c : data.substr(0, 80)) { From 23f768546dbce7aa36b9937bc1489bec75c80779 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Thu, 20 Dec 2018 10:13:17 -0600 Subject: [PATCH 15/16] cli: add read command Signed-off-by: Victor Sui --- ci/cli-test.sh | 7 +++++++ src/zlog.cc | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/ci/cli-test.sh b/ci/cli-test.sh index b9e31b4..79605e9 100755 --- a/ci/cli-test.sh +++ b/ci/cli-test.sh @@ -17,6 +17,13 @@ ${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'just a lil t ${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'and another' ${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log append testlog 'one more and were done' +echo '616e6420616e6f74686572' >> ${EXPECTED_FILE} +${CLI_CMD} --backend lmdb --db-path ${LMDB_DIR} log read testlog 1 >> ${OUTPUT_FILE} +diff ${EXPECTED_FILE} ${OUTPUT_FILE} + +> ${EXPECTED_FILE} +> ${OUTPUT_FILE} + echo 'arthur willey!' >> ${INPUT_FILE} echo 'nautili hunter' >> ${INPUT_FILE} echo 'abcdefghijlmno' >> ${INPUT_FILE} diff --git a/src/zlog.cc b/src/zlog.cc index 3f21a8d..a688225 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -128,6 +128,7 @@ int handle_log(std::vector command, std::shared_ptr { "create", "zlog log create " }, { "append", "zlog log append \nzlog log append -i " }, { "dump", "zlog log dump " }, + { "read", "zlog log read " }, { "trim", "zlog log trim " }, { "fill", "zlog log fill " }, }; @@ -247,6 +248,38 @@ int handle_log(std::vector command, std::shared_ptr std::cout << std::endl; } return 0; + } else if (command[0] == "read") { + if (command.size() != 3) { // read + std::cerr << usages.at("trim") << std::endl; + return 1; + } + uint64_t pos; + try { + pos = std::stoul(command[2]); + } catch (const std::invalid_argument &e) { + std::cerr << e.what() << std::endl; + return 1; + } + std::string data; + int ret = log->Read(pos, &data); + switch (ret) { + case 0: + break; + case -ENODATA: + std::cerr << "invalidated" << std::endl; + return ret; + case -ERANGE: + std::cerr << "free" << std::endl; + return ret; + default: + std::cerr << "log::Read " << ret << std::endl; + return ret; + } + for (char c : data) { + std::cout << std::setfill('0') << std::setw(2) << std::hex << static_cast(c); + } + std::cout << std::endl; + return 0; } else if (command[0] == "trim") { if (command.size() != 3) { // trim std::cerr << usages.at("trim") << std::endl; From 2a0f41c9c04b3817ba13b65f6f2850006ab40aa5 Mon Sep 17 00:00:00 2001 From: Victor Sui Date: Thu, 20 Dec 2018 10:17:32 -0600 Subject: [PATCH 16/16] cli: better error reporting for bad cli calls Signed-off-by: Victor Sui --- src/zlog.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/zlog.cc b/src/zlog.cc index a688225..c66d40e 100644 --- a/src/zlog.cc +++ b/src/zlog.cc @@ -133,6 +133,14 @@ int handle_log(std::vector command, std::shared_ptr { "fill", "zlog log fill " }, }; + if (command.size() > 0 && usages.find(command[0]) == usages.end()) { + std::cerr << "uknown command \"" << command[0] << "\"" << std::endl; + } + + if (command.size() == 1 && usages.find(command[0]) != usages.end()) { + std::cerr << "command requires log name" << std::endl; + } + if (command.size() < 2 || usages.find(command[0]) == usages.end()) { std::cerr << "usage:" << std::endl; for (const auto &usage : usages) {