Line data Source code
1 : /*
2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain
3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany
4 :
5 : This software was partially supported by the
6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
7 :
8 : This software was partially supported by the
9 : ADA-FS project under the SPPEXA project funded by the DFG.
10 :
11 : This file is part of GekkoFS.
12 :
13 : GekkoFS is free software: you can redistribute it and/or modify
14 : it under the terms of the GNU General Public License as published by
15 : the Free Software Foundation, either version 3 of the License, or
16 : (at your option) any later version.
17 :
18 : GekkoFS is distributed in the hope that it will be useful,
19 : but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : GNU General Public License for more details.
22 :
23 : You should have received a copy of the GNU General Public License
24 : along with GekkoFS. If not, see <https://www.gnu.org/licenses/>.
25 :
26 : SPDX-License-Identifier: GPL-3.0-or-later
27 : */
28 :
29 : /* C++ includes */
30 : #include <CLI/CLI.hpp>
31 : #include <nlohmann/json.hpp>
32 : #include <memory>
33 : #include <fmt/format.h>
34 : #include <commands.hpp>
35 : #include <reflection.hpp>
36 : #include <serialize.hpp>
37 : #include <binary_buffer.hpp>
38 :
39 : /* C includes */
40 : #include <sys/types.h>
41 : #include <sys/stat.h>
42 : #include <fcntl.h>
43 : #include <unistd.h>
44 :
45 : using json = nlohmann::json;
46 :
47 536 : struct write_validate_options {
48 : bool verbose{};
49 : std::string pathname;
50 : ::size_t count;
51 :
52 : REFL_DECL_STRUCT(write_validate_options, REFL_DECL_MEMBER(bool, verbose),
53 : REFL_DECL_MEMBER(std::string, pathname),
54 : REFL_DECL_MEMBER(::size_t, count));
55 : };
56 :
57 : struct write_validate_output {
58 : int retval;
59 : int errnum;
60 :
61 : REFL_DECL_STRUCT(write_validate_output, REFL_DECL_MEMBER(int, retval),
62 : REFL_DECL_MEMBER(int, errnum));
63 : };
64 :
65 : void
66 10 : to_json(json& record, const write_validate_output& out) {
67 10 : record = serialize(out);
68 10 : }
69 :
70 : void
71 10 : write_validate_exec(const write_validate_options& opts) {
72 :
73 10 : int fd = ::open(opts.pathname.c_str(), O_WRONLY);
74 :
75 10 : if(fd == -1) {
76 0 : if(opts.verbose) {
77 0 : fmt::print(
78 : "write_validate(pathname=\"{}\", count={}) = {}, errno: {} [{}]\n",
79 0 : opts.pathname, opts.count, fd, errno, ::strerror(errno));
80 0 : return;
81 : }
82 :
83 0 : json out = write_validate_output{fd, errno};
84 0 : fmt::print("{}\n", out.dump(2));
85 :
86 0 : return;
87 : }
88 :
89 :
90 10 : std::string data = "";
91 7323277 : for(::size_t i = 0; i < opts.count; i++) {
92 14646534 : data += char((i % 10) + '0');
93 : }
94 :
95 10 : io::buffer buf(data);
96 :
97 10 : auto rv = ::write(fd, buf.data(), opts.count);
98 :
99 10 : if(opts.verbose) {
100 0 : fmt::print(
101 : "write_validate(pathname=\"{}\", count={}) = {}, errno: {} [{}]\n",
102 0 : opts.pathname, opts.count, rv, errno, ::strerror(errno));
103 10 : return;
104 : }
105 :
106 10 : if(rv < 0 or ::size_t(rv) != opts.count) {
107 0 : json out = write_validate_output{(int) rv, errno};
108 0 : fmt::print("{}\n", out.dump(2));
109 0 : return;
110 : }
111 :
112 :
113 10 : io::buffer bufread(opts.count);
114 :
115 10 : size_t total = 0;
116 10 : do {
117 10 : rv = ::read(fd, bufread.data(), opts.count - total);
118 10 : total += rv;
119 10 : } while(rv > 0 and total < opts.count);
120 :
121 10 : if(rv < 0 and total != opts.count) {
122 0 : json out = write_validate_output{(int) rv, errno};
123 0 : fmt::print("{}\n", out.dump(2));
124 0 : return;
125 : }
126 :
127 10 : if(memcmp(buf.data(), bufread.data(), opts.count)) {
128 10 : rv = 1;
129 10 : errno = 0;
130 10 : json out = write_validate_output{(int) rv, errno};
131 10 : fmt::print("{}\n", out.dump(2));
132 10 : return;
133 : } else {
134 0 : rv = 2;
135 0 : errno = EINVAL;
136 0 : json out = write_validate_output{(int) -1, errno};
137 0 : fmt::print("{}\n", out.dump(2));
138 : }
139 : }
140 :
141 : void
142 268 : write_validate_init(CLI::App& app) {
143 :
144 : // Create the option and subcommand objects
145 268 : auto opts = std::make_shared<write_validate_options>();
146 536 : auto* cmd = app.add_subcommand(
147 : "write_validate",
148 536 : "Execute the write()-read() system call and compare the content of the buffer");
149 :
150 : // Add options to cmd, binding them to opts
151 268 : cmd->add_flag("-v,--verbose", opts->verbose,
152 536 : "Produce human writeable output");
153 :
154 536 : cmd->add_option("pathname", opts->pathname, "Directory name")
155 : ->required()
156 536 : ->type_name("");
157 :
158 536 : cmd->add_option("count", opts->count, "Number of bytes to test")
159 : ->required()
160 536 : ->type_name("");
161 :
162 1082 : cmd->callback([opts]() { write_validate_exec(*opts); });
163 268 : }
|