X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Fbin%2Fmemcp.cc;h=eb7151e65a8680155b565cd1a8870cae48e84792;hb=fd0f1940d4b11f582fc237ff5ccf2c385eaa0e7d;hp=e149ef316df876d531b4019596f6a53abd04cedd;hpb=2e9eb0803f1fc81bfe6c3e2dda0ed2cbe1aa6a76;p=awesomized%2Flibmemcached diff --git a/src/bin/memcp.cc b/src/bin/memcp.cc index e149ef31..eb7151e6 100644 --- a/src/bin/memcp.cc +++ b/src/bin/memcp.cc @@ -20,44 +20,86 @@ #define PROGRAM_VERSION "1.1" #include "common/options.hpp" +#include "common/checks.hpp" +#include #include #include +#include #include #include struct memcp_file { - enum key { + enum class type { basename, relative, absolute - } type; - enum op { + } key; + enum class mode { SET, ADD, REPLACE - } mode; - const char *path; + } op; + char *path; uint32_t flags; time_t expire; }; -static void add_file(std::vector &files, const client_options &opt, const char *file) { - memcp_file::key type = memcp_file::basename; - memcp_file::op mode = memcp_file::SET; +static inline std::string stream2string(const std::istream &istream) { + return dynamic_cast(std::ostringstream{} << istream.rdbuf()).str(); +} + +static memcached_return_t memcp(const client_options &opt, memcached_st &memc, const char *key, + const memcp_file &file) { + std::ifstream fstream{}; + std::istream *istream = check_istream(opt, file.path, fstream); + + if (!istream){ + return MEMCACHED_ERROR; + } + + const char *mode; + memcached_return_t rc; + auto data = stream2string(*istream); + if (file.op == memcp_file::mode::REPLACE) { + mode = "replace"; + rc = memcached_replace(&memc, key, strlen(key), data.c_str(), data.length(), + file.expire, file.flags); + } else if (file.op == memcp_file::mode::ADD) { + mode = "add"; + rc = memcached_add(&memc, key, strlen(key), data.c_str(), data.length(), + file.expire, file.flags); + } else { + mode = "set"; + rc = memcached_set(&memc, key, strlen(key), data.c_str(), data.length(), + file.expire, file.flags); + } + + if (!memcached_success(rc)) { + auto error = memcached_last_error(&memc) + ? memcached_last_error_message(&memc) + : memcached_strerror(&memc, rc); + std::cerr << "Error occurred during memcached_" << mode <<"('" << key << "'): " << error << "\n"; + } + return rc; +} + +static void add_file(std::vector &files, const client_options &opt, char *file) { + memcp_file::type type = memcp_file::type::basename; + memcp_file::mode mode = memcp_file::mode::SET; uint32_t flags = 0; time_t expire = 0; if (opt.isset("absolute")) { - type = memcp_file::absolute; + type = memcp_file::type::absolute; } else if (opt.isset("relative")) { - type = memcp_file::relative; + type = memcp_file::type::relative; } if (opt.isset("replace")) { - mode = memcp_file::REPLACE; + mode = memcp_file::mode::REPLACE; } else if (opt.isset("add")) { - mode = memcp_file::ADD; + mode = memcp_file::mode::ADD; } if (auto flags_str = opt.argof("flags")) { @@ -68,17 +110,37 @@ static void add_file(std::vector &files, const client_options &opt, } if (opt.isset("debug")) { - auto mode_str = mode == memcp_file::REPLACE ? "REPLACE" : mode == memcp_file::ADD ? "ADD" : "SET"; + auto mode_str = mode == memcp_file::mode::REPLACE ? "REPLACE" : mode == memcp_file::mode::ADD ? "ADD" : "SET"; std::cerr << "Scheduling " << mode_str << " '" << file << "' (expire=" << expire << ", flags=" << flags << ").\n"; } files.emplace_back(memcp_file{type, mode, file, flags, expire}); } +static bool path2key(const client_options &opt, memcp_file &file, char **path) { + static char rpath[PATH_MAX + 1]; + if (file.key == memcp_file::type::absolute) { + *path = realpath(file.path, rpath); + if (!*path) { + if (!opt.isset("quiet")) { + perror(file.path); + } + return false; + } + } else if (file.key == memcp_file::type::relative) { + *path = file.path; + } else { + *path = basename((file.path)); + } + return true; +} + int main(int argc, char *argv[]) { - memcached_st memc; std::vector files{}; - client_options opt{PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_DESCRIPTION, "file [file ...]"}; + client_options opt{PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_DESCRIPTION, + "file [file ...]" + "\n\t\t\t# NOTE: order of flags and positional" + "\n\t\t\t# arguments matters on GNU systems)"}; opt.add(nullptr, '-', no_argument, "GNU argv extension") .parse = [&files](client_options &opt_, client_options::extended_option &ext) { @@ -110,9 +172,9 @@ int main(int argc, char *argv[]) { }; opt.add("udp", 'U', no_argument, "Use UDP.") - .apply = [](const client_options &opt, const client_options::extended_option &ext, memcached_st *memc) { + .apply = [](const client_options &opt_, const client_options::extended_option &ext, memcached_st *memc) { if (MEMCACHED_SUCCESS != memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, ext.set)) { - if (!opt.isset("quiet")) { + if (!opt_.isset("quiet")) { std::cerr << memcached_last_error_message(memc) << "\n"; } return false; @@ -135,10 +197,8 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - if (!memcached_create(&memc)) { - if (!opt.isset("quiet")) { - std::cerr << "Failed to initialize memcached client.\n"; - } + memcached_st memc; + if (!check_memcached(opt, memc)) { exit(EXIT_FAILURE); } @@ -147,10 +207,7 @@ int main(int argc, char *argv[]) { } if (files.empty()) { - if (!*argp) { - if (!opt.isset("quiet")) { - std::cerr << "No file(s) provided.\n"; - } + if (!check_argp(opt, argp, "No file(s) provided.")) { memcached_free(&memc); exit(EXIT_FAILURE); } @@ -160,70 +217,27 @@ int main(int argc, char *argv[]) { } auto exit_code = EXIT_SUCCESS; - for (const auto &file : files) { - auto filename = file.path; - std::ifstream filestream{filename, std::ios::in|std::ios::binary}; - - if (!filestream) { - if (!opt.isset("quiet")) { - std::cerr << "Could not open file '" << filename << "'.\n"; - } + for (auto &file : files) { + char *path = nullptr; + if (!path2key(opt, file, &path)) { exit_code = EXIT_FAILURE; - // continue; - } else { - const char *path; - char rpath[PATH_MAX+1]; - - if (file.type == memcp_file::relative) { - path = filename; - } else if (file.type == memcp_file::absolute) { - path = realpath(filename, rpath); - if (!path) { - if (!opt.isset("quiet")) { - perror(filename); - } - exit_code = EXIT_FAILURE; - continue; - } - } else { - path = basename(filename); - } - - std::ostringstream data{}; - data << filestream.rdbuf(); - - memcached_return_t rc; - const char *mode; - if (file.mode == memcp_file::REPLACE) { - mode = "replace"; - rc = memcached_replace(&memc, path, strlen(path), data.str().c_str(), data.str().length(), - file.expire, file.flags); - } else if (file.mode == memcp_file::ADD) { - mode = "add"; - rc = memcached_add(&memc, path, strlen(path), data.str().c_str(), data.str().length(), - file.expire, file.flags); - } else { - mode = "set"; - rc = memcached_set(&memc, path, strlen(path), data.str().c_str(), data.str().length(), - file.expire, file.flags); - } - - if (MEMCACHED_SUCCESS != rc) { - exit_code = EXIT_FAILURE; - - auto error = memcached_last_error(&memc) - ? memcached_last_error_message(&memc) - : memcached_strerror(&memc, rc); - std::cerr << "Error occurred during memcached_" << mode <<"('" << path << "'): " << error << "\n"; - break; - } + continue; + } + auto rc = memcp(opt, memc, path, file); + if (memcached_success(rc)) { if (opt.isset("verbose")) { - std::cerr << path << "\n"; + std::cout << path << "\n"; } + } else { + exit_code = EXIT_FAILURE; } } + if (!check_buffering(opt, memc)) { + exit_code = EXIT_FAILURE; + } + memcached_free(&memc); exit(exit_code); }